Advertisement
regergr

Untitled

Dec 15th, 2018
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.06 KB | None | 0 0
  1. //Данный модуль содержит набор функций/процедур для работы с большими числами в q-ичной системе счисления:
  2. unit LongNumber;
  3.  
  4. {$mode objfpc}
  5.  
  6. interface
  7. uses sysutils;
  8. const
  9. MIN_BASE = 2; MAX_BASE = 36;
  10. //Q: QWord = 1 shl 32;
  11. Q = 10;
  12. type
  13. //Тип длинного целого:
  14. TLongNumber = record
  15. dig: array of QWord; //Буфер, хранящий в себе цифры числа;
  16. inv: boolean; //Знак числа: (+) true, (-) false;
  17. end;
  18.  
  19. TBase = MIN_BASE..MAX_BASE;
  20.  
  21.  
  22. //Формирует длинное число на основе его строкового представления в заданной системе счисления:
  23. function fromString(const str: AnsiString; base: TBase): TLongNumber;
  24.  
  25. //Формирует строковое представление длинного числа в заданной системе счисления:
  26. function toString(const val: TLongNumber; base: TBase): AnsiString;
  27.  
  28. //Присваивает длинному числу значение короткого:
  29. operator:= (val: int64) res: TLongNumber;
  30.  
  31. //Деление длинного на короткое (возвращает целую часть, в последний аргумент записывает остаток):
  32. function divmod(const lhs: TLongNumber; rhs: int32;
  33. out rem: uint32): TLongNumber;
  34. //Деление длинного на короткое (возвращает целую часть):
  35. operator / (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  36. //Умножение длинного на короткое:
  37. operator * (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  38. //Умножение короткого на длинное:
  39. operator * (lhs: int32; const rhs: TLongNumber) ans: TLongNumber;
  40. //Умножение длинных чисел:
  41. operator * (const lhs, rhs: TLongNumber) ans: TLongNumber;
  42. //Сложение длинных чисел:
  43. operator + (const lhs, rhs: TLongNumber) ans: TLongNumber;
  44. //Разность длинных чисел:
  45. operator - (const lhs, rhs: TLongNumber) ans: TLongNumber;
  46. //Унарный минус:
  47. operator - (const val: TLongNumber) ans: TLongNumber;
  48.  
  49. //Меньше либо равно:
  50. operator <= (const lhs, rhs: TLongNumber) ans: boolean;
  51. //Больше либо равно:
  52. operator >= (const lhs, rhs: TLongNumber) ans: boolean;
  53. //Не равно:
  54. operator <> (const lhs, rhs: TLongNumber) ans: boolean;
  55. //Меньше:
  56. operator < (const lhs, rhs: TLongNumber) ans: boolean;
  57. //Больше:
  58. operator > (const lhs, rhs: TLongNumber) ans: boolean;
  59. //Равно:
  60. operator = (const lhs, rhs: TLongNumber) ans: boolean;
  61.  
  62. implementation
  63. const
  64. alph36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  65.  
  66. function CompareModule(lhs, rhs: TLongNumber): boolean;
  67. var i: integer;
  68. begin
  69. if (high(lhs.dig) > high(rhs.dig)) then begin
  70. Result := true;
  71. end
  72. else if (high(rhs.dig) > high(lhs.dig)) then begin
  73. Result := false;
  74. end
  75. else if (high(rhs.dig) = high(lhs.dig)) then begin
  76. for i:=high(lhs.dig) downto 0 do begin
  77. if (lhs.dig[i]) > (rhs.dig[i]) then begin
  78. Result := true;
  79. exit;
  80. end;
  81. if (lhs.dig[i] < rhs.dig[i]) then begin
  82. Result := false;
  83. exit;
  84. end;
  85. end;
  86. Result := false;
  87. end;
  88. end;
  89. function CharToLongNumber(val: char; base: TBase): TLongNumber;
  90. var num: int64;
  91. begin
  92. num := Pos(val, alph36);
  93. if (num > 0) and (num-1 < base) then begin
  94. Result := num-1;
  95. end
  96. else
  97. raise Exception.Create('Invalid char ''' + val + '''');
  98.  
  99. end;
  100.  
  101. function fromString(const str: AnsiString; base: TBase): TLongNumber;
  102. var i, n: integer;
  103. res, c: TLongNumber;
  104. begin
  105. res := 0;
  106. if str = '' then exit(res);
  107. if (str = '0') or (str = '-0') then res.inv := true;
  108. if (str[1] = '-') then begin
  109. // res.inv := false;
  110. n := 2;
  111. end
  112. else begin
  113. // res.inv := true;
  114. n := 1;
  115. end;
  116. res.inv := true;
  117. while((str[n] = '0') and (n < Length(str))) do n+=1;
  118.  
  119. for i:=n to length(str) do begin
  120. c := charToLongNumber(str[i], base);
  121. //c := StrToLongNumber(str[i], base);
  122. Res := Res * base + c;
  123. end;
  124. if (str[1] = '-') then begin
  125. res.inv := false;
  126.  
  127. end;
  128. exit(res);
  129.  
  130. end;
  131. function Invers_str(str: AnsiString): AnsiString;
  132. var newS: AnsiString;
  133. i: integer;
  134. begin
  135. for i:=length(str) downto 1 do begin
  136. newS += str[i];
  137. end;
  138. Result := newS;
  139. end;
  140.  
  141. function toString(const val: TLongNumber; base: TBase): AnsiString;
  142. var res, buf: TLongNumber;
  143. c: longWord;
  144. begin
  145. Result := '';
  146. res := val;
  147. buf := base;
  148.  
  149. while (CompareModule(res,buf)) do begin
  150. res := divmod(res, base, c);
  151. Result += IntToStr(c);
  152. end;
  153. res := divmod(res, base, c);
  154. Result += IntToStr(c);
  155. if (res.dig[0] <> 0) then result += IntToStr(res.dig[0]);
  156. if (res.inv = false) then begin
  157. Result += '-';
  158. end;
  159. Result := invers_str(result);
  160. end;
  161.  
  162. operator := (val: int64) res: TLongNumber;
  163. begin
  164. SetLength(res.dig, 1);
  165. res.dig[0] := abs(val);
  166. if (val >= 0) then begin
  167. res.inv := true;
  168. end
  169. else res.inv := false;
  170. end;
  171.  
  172.  
  173. function divmod(const lhs: TLongNumber; rhs: int32; out rem: uint32): TLongNumber;
  174. var buf: QWord;
  175. i, zcount: integer;
  176. begin
  177. rem := 0;
  178. buf := 0;
  179. if (rhs = 0) then begin
  180. raise Exception.Create('DIV BY ZERO');
  181. end;
  182. if ((rhs > 0) and (lhs.inv = true)) or ((rhs < 0) and (lhs.inv = false)) then Result.inv := true
  183. else Result.inv := false;
  184. if (rhs < 0) then rhs *= -1;
  185. SetLength(Result.dig, high(lhs.dig)+1);
  186. for i := high(Result.dig) downto 0 do begin
  187. buf := rem * Q + lhs.dig[i];
  188. Result.dig[i]:= buf div rhs;
  189. rem := buf mod rhs;
  190. end;
  191. zcount := 0;
  192. for i := high(Result.dig) downto 1 do begin
  193. if (result.dig[i] = 0) then zcount += 1
  194. else break;
  195. end;
  196. if zcount > 0 then begin
  197. Setlength(result.dig, length(result.dig) - zcount);
  198. end;
  199.  
  200.  
  201. end;
  202.  
  203. operator / (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  204. var rem: Uint32;
  205. i: integer;
  206. begin
  207. Result := divmod(lhs, rhs, rem);
  208. end;
  209. function Mult(lhs: TLongNumber; b: Int32): TLongNumber;
  210. var
  211. c: QWord;
  212. buf: QWOrd;
  213. i: integer;
  214. begin
  215. c := 0;
  216. SetLength(Result.dig, high(lhs.dig)+1);
  217. for i:=0 to high(Result.dig) do begin
  218. buf := lhs.dig[i] * b + c;
  219. c := buf div Q;
  220. Result.dig[i] := buf mod Q;
  221. end;
  222. if (c > 0) then begin
  223. SetLength(Result.dig, high(Result.dig)+2);
  224. Result.dig[i+1] := c;
  225. end;
  226. end;
  227. operator * (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  228. var b:integer;
  229. begin
  230. if (rhs <> 0) then begin
  231. if ((rhs > 0) and (lhs.inv = true)) or ((rhs < 0) and (lhs.inv = false)) then begin
  232. Result.inv := true;
  233. end
  234. else Result.inv := false;
  235. end
  236. else begin
  237. Result.inv := true;
  238. end;
  239. if (rhs < 0) then begin
  240. b := rhs * -1;
  241. end
  242. else b := rhs;
  243. Result := Mult(lhs, b);
  244. end;
  245.  
  246. operator * (lhs: int32; const rhs: TLongNumber) ans: TLongNumber;
  247. begin
  248. Result := rhs * lhs;
  249. end;
  250.  
  251. operator * (const lhs, rhs: TLongNumber) ans: TLongNumber;
  252. var i, j: integer;
  253. s, buf1, buf2: QWord;
  254. a, b: TLongNumber;
  255. begin
  256. a.dig := copy(lhs.dig);
  257. b.dig := copy(rhs.dig);
  258. a.inv := lhs.inv;
  259. b.inv := rhs.inv;
  260. s := 0;
  261. if (a.dig[0] = 0) and (a.inv = false) then begin
  262. a.inv :=true;
  263. end;
  264. if (b.dig[0] = 0) and (b.inv = false) then begin
  265. b.inv :=true;
  266. end;
  267. if (a.inv = b.inv) then
  268. Result.inv := true
  269. else
  270. Result.inv := false;
  271. if (a = 0) or (b = 0) then begin
  272. Result := 0;
  273. exit;
  274. end
  275. else begin
  276. SetLength(Result.dig, high(a.dig) + high(b.dig) + 1);
  277. for i:=0 to high(Result.dig) do begin
  278. Result.dig[i] := 0;
  279. end;
  280. for i:=0 to high(b.dig) do begin
  281. s := 0;
  282. for j:=0 to high(a.dig) do begin
  283. buf1 := b.dig[i] * a.dig[j];
  284. buf2 := Result.dig[i+j] + s;
  285. s := buf1 div Q + buf2 div Q + (buf1 mod Q + buf2 mod Q) div Q;
  286. Result.dig[i+j] := ((buf1 mod Q) + (buf2 mod Q)) mod Q;
  287. end;
  288. if (s > 0) then begin
  289. if i = high(b.dig) then SetLength(Result.dig, Length(Result.dig) + 1);
  290. Result.dig[i + high(a.dig) + 1] := s;
  291. end;
  292. end;
  293. end;
  294. if (Result.dig[0] = 0) then SetLength(Result.dig, 1);
  295. end;
  296.  
  297.  
  298. function Sum(lhs,rhs: TLongNumber):TLongNumber;
  299. var i: integer;
  300. s: QWord;
  301. TimeResult: QWord;
  302. begin
  303. s := 0;
  304. SetLength(Result.dig, high(lhs.dig)+1);
  305. for i:=0 to high(lhs.dig) do
  306. begin
  307. if (i > high(rhs.dig)) then begin
  308. TimeResult := lhs.dig[i] + 0 + s;
  309. end
  310. else begin
  311. TimeResult := s + lhs.dig[i] + rhs.dig[i];
  312. end;
  313. s := TimeResult div Q;
  314. Result.dig[i] := TimeResult mod Q;
  315. if (i = high(lhs.dig)) and (s > 0) then begin
  316. SetLength(Result.dig, high(lhs.dig)+2);
  317. Result.dig[i+1] := s;
  318. end;
  319. end;
  320. end;
  321.  
  322.  
  323.  
  324.  
  325. function Sub(a, b: TLongNumber): TLongNumber;
  326. var
  327. lhs, rhs: array of QWord;
  328. s, i: integer;
  329. begin
  330. s := 0;
  331. lhs := copy(a.dig);
  332. rhs := copy(b.dig);
  333. SetLength(Result.dig, high(lhs)+1);
  334. for i:=0 to high(lhs) do begin
  335. if (i > high(rhs)) then Result.dig[i] := lhs[i] - 0
  336. else if (lhs[i] < rhs[i]) then begin
  337. Result.dig[i] := Q - (rhs[i] - lhs[i]);
  338. if (rhs[i+1] = 0) then lhs[i+1] := Q - 1
  339. else lhs[i+1] -= 1;
  340. end
  341. else Result.dig[i] := lhs[i] - rhs[i];
  342.  
  343.  
  344. end;
  345. if (Result.dig[0] = 0) then Result := 0;
  346. end;
  347.  
  348.  
  349.  
  350. operator + (const lhs, rhs: TLongNumber) ans: TLongNumber;
  351. var b: TLongNumber;
  352. begin
  353. b := rhs;
  354. if (rhs.dig[0] = 0) then begin
  355. if (rhs.inv = false)then begin
  356. b := -rhs;
  357. end;
  358. end;
  359.  
  360. if (b.inv = lhs.inv) then begin
  361. if ((lhs > b) and (lhs.inv = true)) or ((lhs < b) and (lhs.inv = false)) then begin
  362. Result := Sum(lhs, b);
  363. Result.inv := lhs.inv;
  364. end
  365. else begin
  366. Result := Sum(b, lhs);
  367. Result.inv := b.inv;
  368. end;
  369.  
  370. end
  371. else begin
  372. if (CompareModule(lhs, b)) then begin
  373. Result := Sub(lhs, b);
  374. Result.inv := lhs.inv;
  375. end
  376. else begin
  377. Result := Sub(b, lhs);
  378. Result.inv := b.inv;
  379. end;
  380. end;
  381.  
  382. end;
  383.  
  384.  
  385.  
  386. operator - (const lhs, rhs: TLongNumber) ans: TLongNumber;
  387. var buf: TLongNumber;
  388. begin
  389.  
  390. if (lhs.inv = rhs.inv) then begin
  391. if (CompareModule(lhs, rhs)) then begin
  392. Result := Sub(lhs, rhs);
  393. Result.inv := lhs.inv;
  394. end
  395. else begin
  396. buf := -lhs;
  397. Result := Sub(rhs, buf);
  398. Result.inv := buf.inv;
  399. end;
  400. end
  401. else begin
  402. if (CompareModule(lhs, rhs)) then begin
  403. Result.inv := lhs.inv;
  404. buf := -lhs;
  405. Result := Sum(lhs, rhs);
  406.  
  407. end
  408. else begin
  409. Result.inv := lhs.inv;
  410. buf := -lhs;
  411. Result := Sum(rhs, lhs);
  412.  
  413. end;
  414. end;
  415. if (Result.dig[0] = 0) then begin
  416. Result.inv := true;
  417. end;
  418. end;
  419. operator - (const val: TLongNumber) ans: TLongNumber;
  420. begin
  421. Result := val;
  422. if (val.inv = true) then begin
  423. Result.inv := false;
  424. end
  425. else begin
  426. Result.inv := true;
  427. end;
  428. end;
  429.  
  430. operator <= (const lhs, rhs: TLongNumber) ans: boolean;
  431.  
  432. begin
  433. if (lhs = rhs) or (lhs < rhs) then begin
  434. Result := true;
  435. end
  436. else Result := false;
  437. end;
  438.  
  439. operator >= (const lhs, rhs: TLongNumber) ans: boolean;
  440.  
  441. begin
  442. if (lhs = rhs) or (lhs > rhs) then begin
  443. Result := true;
  444. end
  445. else Result := false;
  446. end;
  447.  
  448. operator <> (const lhs, rhs: TLongNumber) ans: boolean;
  449.  
  450. begin
  451. Result := not (lhs = rhs);
  452.  
  453.  
  454. end;
  455.  
  456. operator < (const lhs, rhs: TLongNumber) ans: boolean;
  457. begin
  458. if not (lhs = rhs) and not (lhs > rhs) then begin
  459. Result := true;
  460. end
  461. else begin
  462. Result := false;
  463. end;
  464.  
  465. end;
  466.  
  467. operator > (const lhs, rhs: TLongNumber) ans: boolean;
  468. var lLen, rLen, i: integer;
  469. begin
  470. lLen := high(lhs.dig);
  471. rlen := high(rhs.dig);
  472. if (lhs.inv = false) and (rhs.inv = true) then begin
  473. Result := false;
  474. exit;
  475. end;
  476. if (lhs.inv = true) and (lhs.inv = false) then begin
  477. Result := true;
  478. exit;
  479. end;
  480. if (lhs.inv = true) and (rhs.inv = true) then begin
  481. if (lLen < rLen) then begin
  482. Result := false;
  483. end;
  484. if (lLen > rLen) then begin
  485. Result := true;
  486. end;
  487. if (lLen = rLen) then begin
  488. for i:=high(lhs.dig)downto 0 do begin
  489. if (lhs.dig[i] < rhs.dig[i]) then begin
  490. Result := false;
  491. exit;
  492. end;
  493. if (lhs.dig[i] > rhs.dig[i]) then begin
  494. Result := true;
  495. exit;
  496. end;
  497. end;
  498. Result := false;
  499. end;
  500. end;
  501. if (lhs.inv = false) and (rhs.inv = false) then begin
  502. if (lLen < rLen) then begin
  503. Result := true;
  504. end;
  505. if (lLen > rLen) then begin
  506. Result := false;
  507. end;
  508. if (lLen = rLen) then begin
  509. for i:=high(lhs.dig) to 0 do begin
  510. if (lhs.dig[i] < rhs.dig[i]) then begin
  511. Result := true;
  512. exit;
  513. end;
  514. if (lhs.dig[i] > rhs.dig[i]) then begin
  515. Result := false;
  516. exit;
  517. end;
  518. end;
  519. Result := false;
  520. end;
  521.  
  522. end;
  523. end;
  524.  
  525. operator = (const lhs, rhs: TLongNumber) ans: boolean;
  526. var lLen, rLen, i: integer;
  527. begin
  528. lLen := high(lhs.dig);
  529. rlen := high(rhs.dig);
  530. if (rhs.inv = lhs.inv) then begin
  531. if (lLen = rLen) then begin
  532. for i:=high(lhs.dig) downto 0 do begin
  533. if (lhs.dig[i] <> rhs.dig[i]) then begin
  534. Result := false;
  535. exit;
  536. end;
  537. end;
  538. Result := true;
  539. exit;
  540. end
  541. else begin
  542. Result := false;
  543. exit;
  544. end;
  545. end
  546. else begin
  547. Result := false;
  548. exit;
  549. end;
  550. end;
  551.  
  552. //...
  553.  
  554. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement