Advertisement
Pweebs

Untitled

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