Advertisement
Guest User

Untitled

a guest
May 20th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.26 KB | None | 0 0
  1. // A big counter is an arbitrary precision positive integer which you can add or subtract values from.
  2. // If any value goes below zero it returns zero.
  3. // Example Usage
  4. // n = BigCounter("9999999999999999999999999")
  5. // n.add("7777777777777777777")
  6. // n.subtract("1");
  7. // n.greaterThan("100"); -- true
  8.  
  9. // creates a big counter array from a string or number.
  10. BigCounter.runTests = function(){
  11. console.log("Running BigCounter test cases. . . ");
  12. n = BigCounter("9999999999999999999999999")
  13. console.log('n = BigCounter("9999999999999999999999999"): ' + n);
  14. console.log('n.add("7777777777777777777"): ' + n.add("7777777777777777777"));
  15. console.log('n.subtract("1"): ' + n.subtract("1"));
  16. console.log('n.greaterThan("100"): ' + n.greaterThan("100"));
  17. console.log('n.subtract("9999999999999999999999999999999999"): ' + n.subtract("9999999999999999999999999999999999"));
  18. console.log('n.greaterThan("100"): ' + n.greaterThan("100"));
  19. }
  20.  
  21. function BigCounter(x){
  22. BIG_DIGIT_LOG_BASE = 9; // base 1 billion
  23. BIG_DIGIT_BASE = Math.pow(10, BIG_DIGIT_LOG_BASE);
  24.  
  25. var result = [];
  26. if(Array.isArray(x)){
  27. assertBigCounter(x);
  28. return x; }
  29. if(typeof x == "string"){
  30. while(x.length > 0){
  31. var i = x.length-BIG_DIGIT_LOG_BASE;
  32. result.unshift(parseInt(x.substring(i)));
  33. x = x.substring(0,i); }}
  34. else{ result.unshift(parseInt(x)); }
  35. result.toString = bigCounterToString;
  36. result.add = function(other){ return bigAdd2(this, BigCounter(other)); }
  37. result.subtract = function(other){ return bigSubtract2(this, BigCounter(other)); }
  38. result.equals = function(other){ return this.toString() == other.toString(); }
  39. result.greaterThan = function(other){
  40. var s = other.toString();
  41. var t = this.toString();
  42. if(s.length > t.length) return false;
  43. if(t.length > s.length) return true;
  44. return t > s; // lexicographical comparison works if they are the same length
  45. }
  46. result.lessThan = function(other){
  47. var s = other.toString();
  48. var t = this.toString();
  49. if(s.length < t.length) return false;
  50. if(t.length < s.length) return true;
  51. return t < s;
  52. }
  53. return result;
  54.  
  55. // converts a big counter array to a string
  56. function bigCounterToString(n){
  57. if(n === undefined) n = this;
  58. assertBigCounter(n);
  59. if(n.length == 1 && n[0] == 0) return "0";
  60. var result = n.reduce(function(s,x){
  61. return (s? s: "") + (x + BIG_DIGIT_BASE).toString().substring(1); });
  62. return result.substring(result.indexOf(/[^0]/));
  63. }
  64.  
  65. // should be array of integers in range [0, BIG_DIGIT_BASE)
  66. function assertBigCounter(n){
  67. if(!Array.isArray(n)){
  68. throw new Error("Big counter should be array"); }
  69. for(var i=0; i < n.length; ++i){
  70. var digit = n[i];
  71. if(isNaN(digit)){
  72. throw new Error("Big counter digit not a number: " + digit); }
  73. if(digit < 0 || digit >= BIG_DIGIT_BASE){
  74. throw new Error("Big counter digit out of range"); }
  75. if(n.length > 1 && i==0 && digit == 0){
  76. throw new Error("Big counter leading digit was zero."); }
  77. if(digit - Math.round(digit) > 0.0001){
  78. throw new Error("Big counter digit not an integer"); }
  79. }
  80. }
  81.  
  82. // add a small number to the counter and return a value.
  83. //function bigAdd(n, x){
  84. // assertBigCounter(n);
  85. // n[n.length-1] += x;
  86. // return bigCarryOrBorrow(n);
  87. //}
  88. // these functions both operate in place and return the value.
  89. // add 2 big counters
  90. function bigAdd2(n, m){
  91. var n_len = n.length;
  92. var m_len = m.length;
  93. var len = Math.min(m_len, n_len);
  94. for(var i=1; i<=len; ++i){
  95. n[n_len-i] += m[m_len-i]; }
  96. if(m_len > n_len){
  97. for(var i=n_len + 1; i<=m_len; ++i){
  98. n.unshift(m[m_len - i]); }}
  99. // console.log("n", n, "m", m);
  100. return bigCarryOrBorrow(n);
  101. }
  102.  
  103. function bigSubtract2(n, m){
  104. var n_len = n.length;
  105. var m_len = m.length;
  106. if(m_len > n_len){
  107. console.warn("BigCounter: Negative value changed to zero");
  108. n[0] = 0;
  109. n.length = 1;
  110. return n; }
  111. for(var i=1; i<=m_len; ++i){
  112. n[n_len-i] -= m[m_len-i]; }
  113. return bigCarryOrBorrow(n);
  114. }
  115.  
  116. // carry or borrow
  117. // may not go below zero.
  118. function bigCarryOrBorrow(n){
  119. for(var i=n.length-1; i >= 0; --i){
  120. var x = n[i];
  121. if(x >= BIG_DIGIT_BASE || (x < 0 && i > 0)){
  122. var extra = Math.floor(x/BIG_DIGIT_BASE);
  123. n[i] -= extra * BIG_DIGIT_BASE;
  124. if(i == 0){
  125. n.unshift(extra);
  126. ++i; }
  127. n[i-1] += extra;
  128. }
  129. }
  130. while(n.length > 1 && n[0] == 0){
  131. n.shift(); }
  132. if(n.length && n[0] < 0){
  133. console.warn("BigCounter: Negative value changed to zero");
  134. n[0] = 0;
  135. n.length = 1; }
  136. return n;
  137. }
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement