Advertisement
Guest User

bigcounter.js

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