Advertisement
Pweebs

Untitled

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