ArinaRaguzina

Untitled

Dec 15th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.65 KB | None | 0 0
  1. //Данный модуль содержит набор функций/процедур для работы с большими числами в q-ичной системе счисления:
  2. unit LongNumberFib;
  3.  
  4. {$mode objfpc}
  5.  
  6. interface
  7.  
  8. const
  9. TRUE_BASE = qword(1) shl 32;
  10. MIN_BASE = 2; MAX_BASE = 36;
  11.  
  12. type
  13. //Тип длинного целого:
  14. TLongNumber = record
  15. dig: array of uint32; //Буфер, хранящий в себе цифры числа;
  16. inv: boolean; //Знак числа: (+) true, (-) false;
  17. end;
  18.  
  19. TBase = MIN_BASE..MAX_BASE;
  20.  
  21. //Формирует длинное число на основе его строкового представления в заданной системе счисления:
  22. function fromString(const str: AnsiString; base: TBase): TLongNumber;
  23.  
  24. //Формирует строковое представление длинного числа в заданной системе счисления:
  25. function toString(const val: TLongNumber; base: TBase): AnsiString;
  26.  
  27. //Присваивает длинному числу значение короткого:
  28. operator:= (val: int64) res: TLongNumber;
  29.  
  30. //Деление длинного на короткое (возвращает целую часть, в последний аргумент записывает остаток):
  31. function divmod(const lhs: TLongNumber; rhs: int32;
  32. out rem: uint32): TLongNumber;
  33. //Деление длинного на короткое (возвращает целую часть):
  34. operator / (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  35. //Умножение длинного на короткое:
  36. operator * (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  37. //Умножение короткого на длинное:
  38. operator * (lhs: int32; const rhs: TLongNumber) ans: TLongNumber;
  39. //Умножение длинных чисел:
  40. operator * (const lhs, rhs: TLongNumber) ans: TLongNumber;
  41. //Сложение длинных чисел:
  42. operator + (const lhs, rhs: TLongNumber) ans: TLongNumber;
  43. //Разность длинных чисел:
  44. operator - (const lhs, rhs: TLongNumber) ans: TLongNumber;
  45. //Унарный минус:
  46. operator - (const val: TLongNumber) ans: TLongNumber;
  47.  
  48. //Меньше либо равно:
  49. operator <= (const lhs, rhs: TLongNumber) ans: boolean;
  50. //Больше либо равно:
  51. operator >= (const lhs, rhs: TLongNumber) ans: boolean;
  52. //Не равно:
  53. operator <> (const lhs, rhs: TLongNumber) ans: boolean;
  54. //Меньше:
  55. operator < (const lhs, rhs: TLongNumber) ans: boolean;
  56. //Больше:
  57. operator > (const lhs, rhs: TLongNumber) ans: boolean;
  58. //Равно:
  59. operator = (const lhs, rhs: TLongNumber) ans: boolean;
  60.  
  61. implementation
  62.  
  63. //Здесь нужно дописать реализацию объявленных выше функций!
  64.  
  65. function ToChar(a:uint32): char;
  66. const s:string='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  67. begin
  68. ToChar:=s[a+1];
  69. end;
  70.  
  71. function ToQword(a:char): QWord;
  72. const s:string='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  73. begin
  74. ToQword:= pos(a,s)-1;
  75. end;
  76. function MultLongLong(lhs,rhs:TLongNumber; inv:boolean):TLongNumber;
  77. var i,j,remain:uint64;
  78. begin
  79. SetLength(result.dig,length(lhs.dig) + length(rhs.dig));
  80. result.inv := inv;
  81. for i := 0 to length(lhs.dig)-1 do
  82. begin
  83. remain := 0;
  84. for j := 0 to length(rhs.dig)-1 do
  85. begin
  86. remain := remain + lhs.dig[i] * rhs.dig[j] + Result.dig[i+j];
  87. Result.dig[i+j] := remain mod TRUE_BASE;
  88. remain := remain div TRUE_BASE;
  89. end;
  90. if remain > 0 then
  91. Result.dig[i + length(rhs.dig)] += remain;
  92. end;
  93. end;
  94.  
  95. function MutlLongShort(lhs:TLongNumber; rhs:int32; lengthLong:uint32; invLong:boolean):TLongNumber;
  96. var i,remain:qword;
  97. invShort:boolean;
  98. begin
  99. invShort := true;
  100. if rhs < 0 then
  101. begin
  102. invShort := false;
  103. rhs := abs(rhs);
  104. end;
  105. if invLong = invShort then
  106. lhs.inv := true
  107. else
  108. lhs.inv := false;
  109. if (lhs.dig[lengthLong - 1] > TRUE_BASE div rhs) then
  110. SetLength(lhs.dig, lengthLong + 1);
  111. remain := 0;
  112. for i := 0 to (lengthLong - 1) do
  113. begin
  114. remain := remain + lhs.dig[i] * rhs;
  115. lhs.dig[i] := remain mod TRUE_BASE;
  116. remain := remain div TRUE_BASE;
  117. end;
  118. if remain > 0 then
  119. lhs.dig[lengthLong] += remain;
  120. exit(lhs);
  121. end;
  122. function Swap(lhs,rhs:TLongNumber):TLongNumber;
  123. var t:TLongNumber;
  124. begin
  125. t:=rhs;
  126. rhs:=lhs;
  127. lhs:=t;
  128. end;
  129.  
  130. function Sum(lhs,rhs:TLongNumber; n1,n2:uint32; inv:boolean):TLongNumber;
  131. var ost:uint32;
  132. i:uint32;
  133. begin
  134. ost := 0;
  135. i := 0;
  136. if (lhs.dig[n2 - 1] > TRUE_BASE - rhs.dig[n2 - 1]) then
  137. setLength(lhs.dig,n1 + 1);
  138. for i := 0 to n2 - 1 do
  139. begin
  140. ost := lhs.dig[i] + rhs.dig[i] + ost;
  141. lhs.dig[i] := ost mod TRUE_BASE;
  142. ost := ost div TRUE_BASE;
  143. end;
  144. for i:= n2 to n1 do
  145. begin
  146. if ost = 0 then break;
  147. ost:=lhs.dig[i] + ost;
  148. lhs.dig[i] := ost mod TRUE_BASE;
  149. ost := ost div TRUE_BASE;
  150. end;
  151. lhs.inv := inv;
  152. exit(lhs);
  153. end;
  154.  
  155. function Min(lhs,rhs:TLongNumber):TLongNumber;
  156. var Inv:boolean;
  157. i,t:uint32;
  158. begin
  159. lhs.inv := true;
  160. rhs.inv := true;
  161. inv:=lhs.inv;
  162. i:= 0;
  163. t:= 0;
  164. if rhs > lhs then
  165. begin
  166. swap(lhs,rhs);
  167. lhs.inv := not(inv);
  168. end
  169. else
  170. lhs.inv := inv;
  171. for i := 0 to length(rhs.dig) - 1 do
  172. begin
  173. t := lhs.dig[i] - rhs.dig[i] - t;
  174. if (t < 0) then
  175. begin
  176. lhs.dig[i] := TRUE_BASE-abs(t);
  177. t := 1;
  178. end
  179. else
  180. begin
  181. lhs.dig[i] := t;
  182. t := 0;
  183. end
  184. end;
  185. for i := length(rhs.dig) to length(lhs.dig) - 1 do
  186. begin
  187. if t = 0 then
  188. break;
  189. t := lhs.dig[i] - t;
  190. if (t < 0) then
  191. begin
  192. lhs.dig[i] := TRUE_BASE + t;
  193. t := 1;
  194. end
  195. else
  196. begin
  197. lhs.dig[i] := t;
  198. t := 0;
  199. end;
  200.  
  201. end;
  202. exit(lhs);
  203. end;
  204.  
  205. function FromString(const str: AnsiString; base: TBase): TLongNumber;
  206. var
  207. n: uint32;
  208. i,k: integer;
  209. ans: TLongNumber;
  210. begin
  211. ans:=0;
  212. k:=1;
  213. if str[1] = '-' then
  214. k+=1;
  215. for i:=k to Length(str) do begin
  216. n:= ToQword(str[i]);
  217. ans:=ans*base;
  218. ans:=ans+n;
  219. end;
  220. if str[1] = '-' then
  221. ans.inv:= False
  222. else
  223. ans.inv:= True;
  224. fromString:= ans;
  225. end;
  226.  
  227. function toString(const val: TLongNumber; base: TBase): AnsiString;
  228. var
  229. str:AnsiString;
  230. r:uint32;
  231. loc1, loc2: TLongNumber;
  232. begin
  233. loc1.inv:=val.inv;
  234. loc2:=val;
  235. loc2.inv:= True;
  236. if (Length(val.dig) = 1) and (val.dig[0] = 0) then
  237. str:='0'
  238. else begin
  239. while loc2 <> 0 do begin
  240. loc2:= divmod(loc2, base, r);
  241. str:= ToChar(r) + str;
  242. end;
  243. if loc1.inv = False then
  244. str:= '-' + str;
  245. end;
  246. toString:= str;
  247. end;
  248.  
  249. operator := (val: int64) res: TLongNumber;
  250. var
  251. i: integer;
  252. q: QWord;
  253. begin
  254. q:= QWord(1) shl 32;
  255. SetLength(res.dig, 0);
  256. i:=0;
  257. if val >= 0 then
  258. res.inv:= True
  259. else
  260. res.inv:= False;
  261. val:= abs(val);
  262. while (val > 0) do begin
  263. SetLength(res.dig, i+1);
  264. res.dig[i]:= val mod q;
  265. val:= val div q;
  266. inc(i);
  267. end;
  268. if Length(res.dig) = 0 then begin
  269. SetLength(res.dig,1);
  270. res.dig[0] := 0;
  271. end;
  272. end;
  273.  
  274.  
  275. function divmod(const lhs: TLongNumber; rhs: int32;
  276. out rem: uint32): TLongNumber;
  277. var i:uint32;
  278. remain:qword;
  279. invShort:boolean;
  280. begin
  281. SetLength(Result.dig,length(lhs.dig));
  282. invShort := true;
  283. if rhs < 0 then
  284. begin
  285. invShort := false;
  286. rhs := abs(rhs);
  287. end;
  288. if lhs.inv = invShort then
  289. Result.inv := true
  290. else
  291. Result.inv := false;
  292. remain := 0;
  293. for i := length(lhs.dig) - 1 downto 0 do
  294. begin
  295. remain := lhs.dig[i] + remain * TRUE_BASE;
  296. result.dig[i] := remain div rhs;
  297. remain := remain mod rhs;
  298. end;
  299. rem := remain;
  300. end;
  301.  
  302.  
  303.  
  304. operator / (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  305. var ost:uint32;
  306. begin
  307. ans := divmod(lhs,rhs,ost);
  308. end;
  309.  
  310. operator * (const lhs: TLongNumber; rhs: int32) ans: TLongNumber;
  311. begin
  312. ans := MutlLongShort(lhs,rhs,length(lhs.dig),lhs.inv);
  313. end;
  314.  
  315. operator * (lhs: int32; const rhs: TLongNumber) ans: TLongNumber;
  316. begin
  317. ans := MutlLongShort(rhs,lhs,length(rhs.dig),rhs.inv);
  318. end;
  319.  
  320. operator * (const lhs, rhs: TLongNumber) ans: TLongNumber;
  321. begin
  322. if lhs.inv = rhs.inv then
  323. ans := MultLongLong(lhs,rhs,true)
  324. else
  325. ans := MultLongLong(lhs,rhs,false);
  326. end;
  327.  
  328. operator + (const lhs, rhs: TLongNumber) ans: TLongNumber;
  329. begin
  330. if (lhs.inv = rhs.inv) then
  331. begin
  332. if length(lhs.dig) >= length(rhs.dig) then
  333. ans := sum(lhs,rhs,length(lhs.dig),length(rhs.dig),lhs.inv)
  334. else
  335. ans := sum(rhs,lhs,length(rhs.dig),length(lhs.dig),lhs.inv);
  336. end
  337. else
  338. begin
  339. ans := min(lhs,rhs);
  340. end;
  341. end;
  342.  
  343. operator - (const lhs, rhs: TLongNumber) ans: TLongNumber;
  344. begin
  345. if lhs.inv = rhs.inv then
  346. ans := min(lhs,rhs)
  347. else
  348. begin
  349. if length(lhs.dig) >= length(rhs.dig) then
  350. ans:=sum(lhs,rhs,length(lhs.dig),length(rhs.dig),lhs.inv)
  351. else
  352. ans:=sum(rhs,lhs,length(rhs.dig),length(lhs.dig),lhs.inv);
  353. end;
  354.  
  355. end;
  356.  
  357. operator - (const val: TLongNumber) ans: TLongNumber;
  358. begin
  359. ans := val;
  360. ans.inv := not(val.inv);
  361. end;
  362.  
  363. operator <= (const lhs, rhs: TLongNumber) ans: boolean;
  364. begin
  365. ans := (rhs > lhs) or (lhs = rhs);
  366. end;
  367.  
  368. operator >= (const lhs, rhs: TLongNumber) ans: boolean;
  369. begin
  370. ans := (lhs > rhs) or (lhs = rhs);
  371. end;
  372.  
  373. operator <> (const lhs, rhs: TLongNumber) ans: boolean;
  374. begin
  375. ans := not(lhs = rhs);
  376. end;
  377.  
  378. operator < (const lhs, rhs: TLongNumber) ans: boolean;
  379. begin
  380. ans := (rhs > lhs) and (rhs<>lhs);
  381. end;
  382.  
  383. operator > (const lhs, rhs: TLongNumber) ans: boolean;
  384. var i,lengthLeft,lengthRight:uint32;
  385. begin
  386. ans := true;
  387. lengthLeft := length(lhs.dig);
  388. lengthRight := length(rhs.dig);
  389. if lhs.inv = rhs.inv then
  390. begin
  391. if lhs.inv = true then
  392. begin
  393. if(lengthLeft < lengthRight) then exit(false)
  394. else if (lengthLeft = lengthRight) then
  395. begin
  396. for i := lengthLeft - 1 downto 0 do
  397. begin
  398. if (lhs.dig[i] = rhs.dig[i]) then
  399. ans := false
  400. else if (lhs.dig[i] > rhs.dig[i]) then
  401. exit(true)
  402. else
  403. exit(false);
  404. end;
  405. end;
  406. end
  407. else
  408. begin
  409. if lengthLeft > lengthRight then exit(false)
  410. else if (lengthLeft = lengthRight) then
  411. begin
  412. for i := lengthLeft - 1 downto 0 do
  413. begin
  414. if (lhs.dig[i] = rhs.dig[i]) then
  415. ans:=false
  416. else if (lhs.dig[i] < rhs.dig[i]) then
  417. exit(true)
  418. else
  419. exit(false);
  420. end;
  421. end;
  422. end;
  423. end
  424. else
  425. if rhs.inv = true then
  426. ans := false;
  427. end;
  428.  
  429. operator = (const lhs, rhs: TLongNumber) ans: boolean;
  430. begin
  431. ans := (not((lhs > rhs) or (rhs > lhs)));
  432. end;
  433.  
  434. end.
Add Comment
Please, Sign In to add comment