Advertisement
Pweebs

Untitled

Nov 16th, 2019
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.77 KB | None | 0 0
  1. // Jevin Olano
  2. // jolano
  3. // CSE 101
  4. // November 9, 2019
  5. // BigInteger.c
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <assert.h>
  10. #include <string.h>
  11. #include "BigInteger.h"
  12. #include "List.h"
  13.  
  14. const int POWER = 9;
  15. const long BASE = 1000000000;
  16.  
  17. // Constructors & Destructors ---------------------------
  18.  
  19. // newBigInteger()
  20. // Returns a reference to a new BigInteger object in the zero state.
  21. BigInteger newBigInteger() {
  22. BigInteger bi = malloc(sizeof(BigIntegerObj));
  23. bi->number = newList();
  24. bi->sign = 0;
  25. return bi;
  26. }
  27.  
  28. // freeBigInteger()
  29. // Frees heap memory associated with *pN, sets *pN to NULL.
  30. void freeBigInteger(BigInteger *pN) {
  31. if (pN != NULL && *pN != NULL) {
  32. BigInteger N = *pN;
  33. makeZero(N);
  34. free(N->number);
  35. free(N);
  36. N = NULL;
  37. }
  38. }
  39.  
  40. // Access Functions -------------------------------------
  41.  
  42. // sign()
  43. // Returns -1 if N is negative, 1 if N is positive, and 0 if N is in the zero state.
  44. int sign(BigInteger N) {
  45. return N->sign;
  46. }
  47.  
  48. // compare()
  49. // Returns -1 if A<B, 1 if A>B, and 0 if A=B.
  50. int compare(BigInteger A, BigInteger B) {
  51. if (A->sign == 0 && B->sign == 0) {
  52. return 0; // if both A & B are in the zero state
  53. }
  54. if (A->sign > B->sign) {
  55. return 1; // if A is positive and B is negative
  56. }
  57. if (A->sign < B->sign) {
  58. return -1; // if A is negative and B is positive
  59. }
  60.  
  61. int lengthA = length(A->number);
  62. int lengthB = length(B->number);
  63. if (lengthA > lengthB && A->sign == 1) {
  64. return 1; // if both A & B are positive and A is longer than B
  65. }
  66. if (lengthA > lengthB && A->sign == -1) {
  67. return -1; // if both A & B are negative and A is longer than B
  68. }
  69. if (lengthB > lengthA && B->sign == 1) {
  70. return -1; // if both A & B are positive and B is longer than A
  71. }
  72. if (lengthB > lengthA && B->sign == -1) {
  73. return 1; // if both A & B are negative and B is longer than A
  74. }
  75.  
  76. BigInteger clonedB = copy(B);
  77.  
  78. // at this point, A & B must be the same sign
  79. moveFront(A->number);
  80. moveFront(clonedB->number);
  81. while (get(A->number) != -1) {
  82. int digitA = get(A->number);
  83. int digitB = get(clonedB->number);
  84. if (digitA > digitB && A->sign == 1) {
  85. return 1;
  86. }
  87. if (digitA < digitB && A->sign == 1) {
  88. return -1;
  89. }
  90. if (digitA > digitB && A->sign == -1) {
  91. return -1;
  92. }
  93. if (digitA < digitB && A->sign == -1) {
  94. return 1;
  95. }
  96. moveNext(A->number);
  97. moveNext(clonedB->number);
  98. }
  99. freeBigInteger(&clonedB);
  100. return 0;
  101. }
  102.  
  103. // equals()
  104. // Return true (1) if A and B are equal, false (0) otherwise.
  105. int equals(BigInteger A, BigInteger B) {
  106. return compare(A, B) == 0 ? 1 : 0;
  107. }
  108.  
  109. // Manipulation Procedures ------------------------------
  110.  
  111. // makeZero()
  112. // Re-sets N to the zero state.
  113. void makeZero(BigInteger N) {
  114. if (N->number != NULL) {
  115. clear(N->number);
  116. }
  117. N->sign = 0;
  118. }
  119.  
  120. // negate()
  121. // Reverses the sign of N: positive <--> negative. Does nothing if N is in the zero state.
  122. void negate(BigInteger N) {
  123. N->sign *= -1;
  124. }
  125.  
  126. // BigInteger Arithmetic Operations ---------------------
  127.  
  128. // private helper
  129. long strToLong(char *s, long numChars) {
  130. char buffer[10];
  131. for (int i = 0; i < numChars; i++) {
  132. buffer[i] = s[i];
  133. }
  134. buffer[numChars] = '\0';
  135. return strtol(buffer, NULL, 10);
  136. }
  137.  
  138. // stringToBigInteger()
  139. // Returns a reference to a new BigInteger represented in base 10 by the string s.
  140. // Pre: s is a non-empty string containing only base ten digits {0,1,2,3,4,5,6,7,8,9}
  141. // and an optional sign {+, -} prefix.
  142. BigInteger stringToBigInteger(char* s) {
  143. BigInteger bi = newBigInteger();
  144.  
  145. // handles input = '0'
  146. if (strlen(s) == 1 && s[0] == '0') {
  147. return bi;
  148. }
  149.  
  150. // p is basically a cursor
  151. char *p = s;
  152.  
  153. // checks optional sign prefixes
  154. if (s[0] == '+') {
  155. bi->sign = 1;
  156. p++;
  157. } else if (s[0] == '-') {
  158. bi->sign = -1;
  159. p++;
  160. } else {
  161. bi->sign = 1;
  162. }
  163.  
  164. // check for incomplete digit (incomplete chunk)
  165. int remainder = strlen(p) % POWER;
  166. if (remainder > 0) {
  167. append(bi->number, strToLong(p, remainder));
  168. p += remainder;
  169. }
  170.  
  171. // add "full" digits
  172. int numDigitsLeft = strlen(p) / POWER;
  173. for (int i = 0; i < numDigitsLeft; i++) {
  174. append(bi->number, strToLong(p, POWER));
  175. p += POWER;
  176. }
  177.  
  178. return bi;
  179. }
  180.  
  181. // copy()
  182. // Returns a reference to a new BigInteger object in the same state as N.
  183. BigInteger copy(BigInteger N) {
  184. BigInteger copyInt = newBigInteger();
  185. copyInt->sign = N->sign;
  186. copyInt->number = copyList(N->number);
  187. return copyInt;
  188. }
  189.  
  190. // longerNumLength
  191. // helper method
  192. int longerNumLength(BigInteger A, BigInteger B) {
  193. int lengthA = length(A->number);
  194. int lengthB = length(B->number);
  195. return (lengthA > lengthB) ? lengthA : lengthB;
  196. }
  197.  
  198. // getDigit
  199. // helper method
  200. long getDigit(List L) {
  201. long digit = get(L);
  202. return (digit != -1) ? digit : 0;
  203. }
  204.  
  205. // add()
  206. // Places the sum of A and B in the existing BigInteger S, overwriting its current state: S = A + B
  207. void add(BigInteger S, BigInteger A, BigInteger B) {
  208. BigInteger sumInt = sum(A, B);
  209. makeZero(S);
  210. S->sign = sumInt->sign;
  211. S->number = copyList(sumInt->number);
  212. freeBigInteger(&sumInt);
  213. }
  214.  
  215. void removeLeadingZeroes(BigInteger bi) {
  216. if (isEmpty(bi->number)) {
  217. return;
  218. }
  219. moveFront(bi->number);
  220. while(get(bi->number) != -1) {
  221. if (get(bi->number) != 0) {
  222. return;
  223. }
  224. delete(bi->number);
  225. if (isEmpty(bi->number)) {
  226. return;
  227. }
  228. moveFront(bi->number);
  229. }
  230. }
  231.  
  232. // sum()
  233. // Returns a reference to a new BigInteger object representing A + B.
  234. BigInteger sum(BigInteger A, BigInteger B) {
  235. if (A->sign == 0 && B->sign == 0) {
  236. return newBigInteger();
  237. }
  238. if (A->sign == 0) {
  239. return copy(B);
  240. }
  241. if (B->sign == 0) {
  242. return copy(A);
  243. }
  244.  
  245. if (A->sign == 1 && B->sign == -1) {
  246. negate(B);
  247. BigInteger temp = diff(A, B);
  248. negate(B);
  249. return temp;
  250. }
  251.  
  252. if (A->sign == -1 && B->sign == 1) {
  253. negate(A);
  254. BigInteger temp = diff(B, A);
  255. negate(A);
  256. return temp;
  257. }
  258.  
  259. BigInteger sumInt = newBigInteger();
  260.  
  261. BigInteger clonedB = copy(B);
  262.  
  263. moveBack(A->number);
  264. moveBack(clonedB->number);
  265.  
  266. int longerNumLen = longerNumLength(A, clonedB);
  267.  
  268. int carry = 0;
  269.  
  270. for (int i = 0; i < longerNumLen; i++) {
  271. long digitA = getDigit(A->number);
  272. long digitB = getDigit(clonedB->number);
  273. long sum = digitA + digitB + carry;
  274. carry = 0;
  275. if (sum >= BASE) {
  276. sum -= BASE;
  277. carry = 1;
  278. }
  279. prepend(sumInt->number, sum);
  280. movePrev(A->number);
  281. movePrev(clonedB->number);
  282. }
  283.  
  284. if (carry == 1) {
  285. prepend(sumInt->number, 1);
  286. }
  287.  
  288. sumInt->sign = A->sign; // or B->sign since they're the same
  289. freeBigInteger(&clonedB);
  290. removeLeadingZeroes(sumInt);
  291. return sumInt;
  292. }
  293.  
  294. // copyNegate()
  295. // helper method
  296. BigInteger copyNegate(BigInteger A) {
  297. BigInteger negativeA = copy(A);
  298. negate(negativeA);
  299. return negativeA;
  300. }
  301.  
  302. // subtract()
  303. // Places the difference of A and B in the existing BigInteger D, overwriting its current state: D = A - B
  304. void subtract(BigInteger D, BigInteger A, BigInteger B) {
  305. BigInteger diffInt = diff(A, B);
  306. makeZero(D);
  307. D->sign = diffInt->sign;
  308. D->number = copyList(diffInt->number);
  309. freeBigInteger(&diffInt);
  310. }
  311.  
  312. // diff()
  313. // Returns a reference to a new BigInteger object representing A - B.
  314. BigInteger diff(BigInteger A, BigInteger B) {
  315. if (A->sign == 0 && B->sign == 0) {
  316. return newBigInteger();
  317. }
  318. if (A->sign == 0) {
  319. return copyNegate(B);
  320. }
  321. if (B->sign == 0) {
  322. return copy(A);
  323. }
  324. if (A->sign != B->sign) {
  325. return sum(A, copyNegate(B));
  326. }
  327.  
  328. BigInteger diffInt = newBigInteger();
  329. diffInt->sign = equals(A, B) == 1 ? 0 : A->sign;
  330. BigInteger clonedB = copy(B);
  331.  
  332. moveBack(A->number);
  333. moveBack(clonedB->number);
  334.  
  335. int longerNumLen = longerNumLength(A, clonedB);
  336.  
  337. int borrow = 0;
  338.  
  339. for (int i = 0; i < longerNumLen; i++) {
  340. long digitA = getDigit(A->number);
  341. long digitB = getDigit(clonedB->number);
  342. long diff = digitA - digitB - borrow;
  343. borrow = 0;
  344. if (diff < 0) {
  345. diff += BASE;
  346. borrow = 1;
  347. }
  348. prepend(diffInt->number, diff);
  349. movePrev(A->number);
  350. movePrev(clonedB->number);
  351. }
  352.  
  353. if (borrow == 1) {
  354. moveFront(diffInt->number);
  355. set(diffInt->number, get(diffInt->number) - BASE);
  356. negate(diffInt);
  357. }
  358.  
  359. freeBigInteger(&clonedB);
  360. removeLeadingZeroes(diffInt);
  361. return diffInt;
  362. }
  363.  
  364. // multiply()
  365. // Places the product of A and B in the existing BigInteger P, overwriting its current state: P = A * B
  366. void multiply(BigInteger P, BigInteger A, BigInteger B) {
  367. BigInteger prodInt = prod(A, B);
  368. makeZero(P);
  369. P->sign = prodInt->sign;
  370. P->number = copyList(prodInt->number);
  371. freeBigInteger(&prodInt);
  372. }
  373.  
  374. // prod()
  375. // Returns a reference to a new BigInteger object representing A * B.
  376. BigInteger prod(BigInteger A, BigInteger B) {
  377. if (A->sign == 0 || B->sign == 0) {
  378. return newBigInteger(); // zero state
  379. }
  380.  
  381. BigInteger prodInt = newBigInteger();
  382.  
  383. int carry = 0;
  384. int zeroes = 0;
  385. BigInteger prodTemp = newBigInteger();
  386.  
  387. BigInteger clonedB = copy(B);
  388.  
  389. moveBack(A->number);
  390.  
  391. // A = "bottom" number in traditional multiplication
  392. // B = "top" number in traditional multiplication
  393.  
  394. while (A->number->cursor != NULL) {
  395. moveBack(clonedB->number);
  396. makeZero(prodTemp);
  397. int isNonZero = 0;
  398. while (clonedB->number->cursor != NULL) {
  399. long digitA = getDigit(A->number);
  400. long digitB = getDigit(clonedB->number);
  401. long prod = digitA * digitB + carry;
  402. carry = 0;
  403. if (prod > 0) {
  404. isNonZero = 1;
  405. }
  406. if (prod >= BASE) {
  407. carry = prod/BASE; // integer division drops fractional part
  408. prod -= BASE * carry;
  409. }
  410. prepend(prodTemp->number, prod);
  411. movePrev(clonedB->number);
  412. }
  413.  
  414. if (carry > 0) {
  415. prepend(prodTemp->number, carry);
  416. isNonZero = 1;
  417. carry = 0;
  418. }
  419.  
  420. for (int i = 0; i < zeroes; i++) {
  421. append(prodTemp->number, 0);
  422. }
  423.  
  424. if (isNonZero == 1) {
  425. prodTemp->sign = 1;
  426. }
  427. add(prodInt, prodInt, prodTemp);
  428. zeroes++;
  429. movePrev(A->number);
  430. }
  431.  
  432. freeBigInteger(&prodTemp);
  433. freeBigInteger(&clonedB);
  434.  
  435. prodInt->sign = (A->sign == B->sign) ? 1 : -1;
  436. removeLeadingZeroes(prodInt);
  437. return prodInt;
  438. }
  439.  
  440. // Other Operations -------------------------------------
  441.  
  442. // printBigInteger()
  443. // Prints a base 10 string representation of N to filestream out.
  444. void printBigInteger(FILE* out, BigInteger N) {
  445. char buffer[256];
  446. if (N->sign == 0) {
  447. fprintf(out, "0\n");
  448. return;
  449. }
  450. if (N->sign == -1) {
  451. fprintf(out, "-");
  452. }
  453. moveFront(N->number);
  454. // skip leading zeroes
  455. while (get(N->number) == 0) {
  456. moveNext(N->number);
  457. }
  458. while (get(N->number) != -1) {
  459. sprintf(buffer, "%ld", get(N->number));
  460. if (N->number->cursor != N->number->front && strlen(buffer) < POWER) {
  461. int numZeroes = POWER - strlen(buffer);
  462. for (int i = 0; i < numZeroes; i++) {
  463. fprintf(out, "0");
  464. }
  465. }
  466. fprintf(out, "%s", buffer);
  467. moveNext(N->number);
  468. }
  469. fprintf(out, "\n");
  470. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement