fork download
  1. /*
  2.  * 大数。
  3.  *
  4.  * Date: 2014-04-11
  5.  * Author: Leonardone
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10.  
  11. #define DEBUG_FLAG 0
  12.  
  13. #if DEBUG_FLAG
  14. # define DebugDo(d) d
  15. #else
  16. # define DebugDo(d)
  17. #endif
  18.  
  19. struct _digit;
  20. struct _decimal;
  21. typedef struct _digit Digit, *LPDigit;
  22. typedef struct _decimal Decimal, *LPDecimal;
  23.  
  24. struct _digit {
  25. int value;
  26. LPDigit upper;
  27. LPDigit under;
  28. };
  29.  
  30. struct _decimal {
  31. int point;
  32. int sign;
  33. LPDigit head;
  34. LPDigit tail;
  35. };
  36.  
  37. LPDigit newDigit(void);
  38. LPDigit newDigitByInt(int value);
  39. int countDigits(const LPDecimal dec);
  40. LPDecimal newDecimal(void);
  41. LPDecimal newDecimalByInt(int value);
  42. void printDecimal(const LPDecimal dec);
  43. LPDecimal addDecimal(LPDecimal val1, LPDecimal val2);
  44. LPDecimal mulDecimal(LPDecimal val1, LPDecimal val2);
  45. void releaseDecimal(LPDecimal dec);
  46. void releaseDigit(LPDigit dig);
  47. LPDecimal newDecimalByStr(char *str);
  48.  
  49. int main(void) {
  50.  
  51. LPDecimal d1 = newDecimalByStr("111.11");
  52. LPDecimal d2 = newDecimalByInt(2222);
  53. LPDecimal d3 = newDecimalByStr("999.99999");
  54. LPDecimal d4 = addDecimal(d1, d2);
  55. LPDecimal d5 = addDecimal(d1, d3);
  56. LPDecimal d6 = addDecimal(d2, d3);
  57. LPDecimal d7 = newDecimalByStr("123456789.123456789");
  58. LPDecimal d8 = newDecimalByStr("999999999.999999999");
  59. LPDecimal d9 = addDecimal(d7, d8);
  60.  
  61. printDecimal(d1);
  62. printDecimal(d2);
  63. printDecimal(d3);
  64. printDecimal(d4);
  65. printDecimal(d5);
  66. printDecimal(d6);
  67. printDecimal(d7);
  68. printDecimal(d8);
  69. printDecimal(d9);
  70.  
  71. releaseDecimal(d1);
  72. releaseDecimal(d2);
  73. releaseDecimal(d3);
  74. releaseDecimal(d4);
  75. releaseDecimal(d5);
  76. releaseDecimal(d6);
  77. releaseDecimal(d7);
  78. releaseDecimal(d8);
  79. releaseDecimal(d9);
  80.  
  81. return 0;
  82. }
  83.  
  84. LPDigit newDigit(void) {
  85. return (LPDigit)calloc(1, sizeof(Digit));
  86. }
  87.  
  88. LPDigit newDigitByInt(int value) {
  89. LPDigit dig = newDigit();
  90. if (value > 9) {
  91. dig->upper = newDigitByInt(value / 10);
  92. dig->upper->under = dig;
  93. }
  94. dig->value = value % 10;
  95. return dig;
  96. }
  97.  
  98. int countDigits(const LPDecimal dec) {
  99. LPDigit dig = dec->head;
  100. int i = 0;
  101. while (dig != NULL) {
  102. i++;
  103. dig = dig->under;
  104. }
  105. return i;
  106. }
  107.  
  108. LPDecimal newDecimal(void) {
  109. return newDecimalByInt(0);
  110. }
  111.  
  112. LPDecimal newDecimalByInt(int value) {
  113. LPDecimal dec = (LPDecimal)calloc(1, sizeof(Decimal));
  114. LPDigit dig;
  115. if (value < 0) {
  116. dec->sign = 1;
  117. value *= -1;
  118. }
  119. dec->tail = dig = newDigitByInt(value);
  120. while (dig->upper != NULL) {
  121. dig = dig->upper;
  122. }
  123. dec->head = dig;
  124. dec->point = countDigits(dec);
  125. return dec;
  126. }
  127.  
  128. LPDecimal newDecimalByStr(char *str) {
  129. LPDecimal dec = (LPDecimal)calloc(1, sizeof(Decimal));
  130. LPDigit dig;
  131. if (*str == '-') {
  132. dec->sign = 1;
  133. str++;
  134. } else if (*str == '+') {
  135. str++;
  136. }
  137. while (*str == '0') {
  138. str++;
  139. }
  140. dec->head = dig = newDigit();
  141. if (*str == '.') {
  142. dig->under = newDigit();
  143. dig->under->upper = dig;
  144. dig = dig->under;
  145. dec->point = 1;
  146. } else if (*str >= '0' && *str <= '9') {
  147. while (*str >= '0' && *str <= '9') {
  148. (dec->point)++;
  149. dig->value = (int)*str - '0';
  150. dig->under = newDigit();
  151. dig->under->upper = dig;
  152. dig = dig->under;
  153. str++;
  154. }
  155. } else {
  156. free(dec);
  157. releaseDigit(dig);
  158. return NULL;
  159. }
  160. if (*str == '.') {
  161. str++;
  162. while (*str >= '0' && *str <= '9') {
  163. dig->value = (int)*str - '0';
  164. dig->under = newDigit();
  165. dig->under->upper = dig;
  166. dig = dig->under;
  167. str++;
  168. }
  169. }
  170. dec->tail = dig->upper;
  171. dec->tail->under = NULL;
  172. dig->upper = NULL;
  173. releaseDigit(dig);
  174. return dec;
  175. }
  176.  
  177. void releaseDigit(LPDigit dig) {
  178. if (dig->under != NULL) {
  179. dig->under->upper = NULL;
  180. releaseDigit(dig->under);
  181. dig->under = NULL;
  182. }
  183. if (dig->upper != NULL) {
  184. dig->upper->under = NULL;
  185. releaseDigit(dig->upper);
  186. dig->upper = NULL;
  187. }
  188. DebugDo(printf("release Digit: %d\n", dig->value));
  189. free(dig);
  190. }
  191.  
  192. void releaseDecimal(LPDecimal dec) {
  193. DebugDo(printf("release Decimal: "));
  194. DebugDo(printDecimal(dec));
  195. releaseDigit(dec->head);
  196. dec->head = NULL;
  197. dec->tail = NULL;
  198. free(dec);
  199. }
  200.  
  201. void printDecimal(const LPDecimal dec) {
  202. int p = dec->point;
  203. LPDigit dig = dec->head;
  204. if (dec->sign) {
  205. putchar('-');
  206. }
  207. while (p > 1 && dig != NULL && dig->value == 0) {
  208. dig = dig->under;
  209. p--;
  210. }
  211. while (p > 0 && dig != NULL) {
  212. putchar('0' + (char)dig->value);
  213. dig = dig->under;
  214. p--;
  215. }
  216. if (p > 0) {
  217. printf("error\n");
  218. exit(1);
  219. }
  220. if (dig != NULL) {
  221. putchar('.');
  222. while (dig != NULL) {
  223. putchar('0' + (char)dig->value);
  224. dig = dig->under;
  225. }
  226. }
  227. putchar('\n');
  228. }
  229.  
  230. LPDecimal addDecimal(LPDecimal val1, LPDecimal val2) {
  231. LPDecimal val3 = newDecimal();
  232. LPDigit dig1 = val1->tail;
  233. LPDigit dig2 = val2->tail;
  234. LPDigit dig3 = val3->tail;
  235. int p1 = val1->point;
  236. int p2 = val2->point;
  237. int c1 = countDigits(val1) - p1;
  238. int c2 = countDigits(val2) - p2;
  239. int c3 = c1 > c2 ? c1 : c2;
  240. int t1, t2, t3, ca;
  241.  
  242. if (val1->sign != val2->sign) {
  243. return val3; /* difDecimal() */
  244. }
  245. val3->sign = val1->sign;
  246.  
  247. while (c1 < c2) {
  248. dig3->value = dig2->value;
  249. dig3->upper = newDigit();
  250. dig3->upper->under = dig3;
  251. dig2 = dig2->upper;
  252. dig3 = dig3->upper;
  253. c2--;
  254. }
  255. while (c1 > c2) {
  256. dig3->value = dig1->value;
  257. dig3->upper = newDigit();
  258. dig3->upper->under = dig3;
  259. dig1 = dig1->upper;
  260. dig3 = dig3->upper;
  261. c1--;
  262. }
  263. ca = 0;
  264. while (dig1 != NULL || dig2 != NULL) {
  265. if (dig1 != NULL) {
  266. t1 = dig1->value;
  267. dig1 = dig1->upper;
  268. } else {
  269. t1 = 0;
  270. }
  271. if (dig2 != NULL) {
  272. t2 = dig2->value;
  273. dig2 = dig2->upper;
  274. } else {
  275. t2 = 0;
  276. }
  277. t3 = t1 + t2 + ca;
  278. ca = t3 / 10;
  279. dig3->value = t3 % 10;
  280. dig3->upper = newDigit();
  281. dig3->upper->under = dig3;
  282. dig3 = dig3->upper;
  283. }
  284. if (ca > 0) {
  285. dig3->value = ca;
  286. val3->head = dig3;
  287. } else {
  288. val3->head = dig3->under;
  289. val3->head->upper = NULL;
  290. dig3->under = NULL;
  291. releaseDigit(dig3);
  292. }
  293. val3->point = countDigits(val3) - c3;
  294.  
  295. return val3;
  296. }
  297.  
  298. LPDecimal mulDecimal(LPDecimal val1, LPDecimal val2) {
  299. return NULL;
  300. }
Success #stdin #stdout 0s 2428KB
stdin
Standard input is empty
stdout
111.11
2222
999.99999
2333.11
1111.10999
3221.99999
123456789.123456789
999999999.999999999
1123456789.123456788