Advertisement
Pweebs

Untitled

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