Advertisement
Pweebs

Arithmetic final 11/14

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