Advertisement
avialaynen

JS calc

Mar 1st, 2013
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <script type="text/javascript">
  2.     //инициация операндов
  3.     var operand1 = '9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999';
  4.     var operand2 = '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112';
  5.     //действие
  6.     var operation = '/';
  7.    
  8.     document.write(operand1 + '<br>' + operation + '<br>' + operand2 + '<br>=<br>');
  9.     document.write(calc(operand1, operand2, operation));
  10.    
  11.     //главная функция вычисления
  12.     function calc(op1, op2, operation)
  13.     {
  14.         //строка для результата
  15.         var result = '';
  16.         //знаки операндов (false - плюс, true - минус)
  17.         var sign1 = false;
  18.         var sign2 = false;
  19.         if(op1[0] == '-')
  20.         {
  21.             sign1 = true;
  22.             op1 = op1.substr(1);    //отрезаем знак от числа
  23.         }
  24.         if(op2[0] == '-')
  25.         {
  26.             sign2 = true;
  27.             op2 = op2.substr(1);
  28.         }
  29.            
  30.         if(operation == '-')
  31.         {
  32.             sign2 = !sign2;     //меняем знак у второго операнда
  33.             operation = '+';    //и работаем как со сложением
  34.         }
  35.        
  36.         if(operation == '+')
  37.         {
  38.             if(!sign1 && !sign2)
  39.                 result = adding(op1, op2);
  40.             if(!sign1 && sign2)
  41.                 result = substract(op1, op2);
  42.             if(sign1 && !sign2)
  43.                 result = substract(op2, op1);
  44.             if(sign1 && sign2)
  45.                 result = '-' + adding(op1, op2);
  46.         }
  47.        
  48.         if(operation == '*')
  49.         {
  50.             //при умножении чисел с разным знаком результат будет отрицательным, иначе - положительным
  51.             sign = '';
  52.             if(sign1 != sign2) sign = '-';
  53.            
  54.             result = sign + multiply(op1, op2);
  55.         }
  56.        
  57.         if(operation == '/')
  58.         {
  59.             //при делении чисел с разным знаком результат будет отрицательным, иначе - положительным
  60.             sign = '';
  61.             if(sign1 != sign2) sign = '-';
  62.            
  63.             result = sign + divide(op1, op2);
  64.         }
  65.        
  66.         return result;
  67.     }
  68.    
  69.     //сложение
  70.     function adding(op1, op2)
  71.     {
  72.         var result = '';
  73.         //перенос из младшего разряда в старший
  74.         var shift = 0;
  75.        
  76.         //нормализация длины операндов
  77.         var diff = op1.length - op2.length;
  78.         if(diff > 0)
  79.             op2 = addZeroToBegin(op2, diff);
  80.         if(diff < 0)
  81.             op1 = addZeroToBegin(op1, - diff);
  82.        
  83.         for(var i = op1.length - 1; i >= 0; i--)
  84.         {
  85.             //считаем текущий разряд
  86.             var currByte = parseInt(op1.charAt(i)) + parseInt(op2.charAt(i)) + shift;
  87.             shift = currByte / 10 | 0;
  88.             currByte = currByte % 10;
  89.             result = currByte.toString() + result;
  90.         }
  91.         if(shift != 0)
  92.             result = shift.toString() + result;
  93.         return result;
  94.     }
  95.    
  96.     //вычитание
  97.     function substract(op1, op2)
  98.     {
  99.         var result = '';
  100.         var sign = '';
  101.  
  102.         //нормализация длины операндов
  103.         var diff = op1.length - op2.length;
  104.         if(diff > 0)
  105.             op2 = addZeroToBegin(op2, diff);
  106.         if(diff < 0)
  107.             op1 = addZeroToBegin(op1, - diff);
  108.        
  109.         //перед выполнением вычитания проверим, действительно ли уменьшаемое больше вычитаемого
  110.         //в противном случае нам нужно поменять их местами, а разность взять со знаком минус
  111.         for(var i = 0; i < op1.length; i++)
  112.         {
  113.             if(op1[i] > op2[i]) break;
  114.             if(op1[i] < op2[i])
  115.             {
  116.                 var temp = op1;
  117.                 op1 = op2;
  118.                 op2 = temp;
  119.                 sign = '-';
  120.                 break;
  121.             }
  122.         }
  123.        
  124.         //заём из старшего разряда в младший
  125.         var shift = 0;
  126.        
  127.         for(var i = op1.length - 1; i >= 0; i--)
  128.         {
  129.             //считаем текущий разряд
  130.             var currByte = parseInt(op1.charAt(i)) - parseInt(op2.charAt(i)) - shift;
  131.             if(currByte < 0)
  132.             {
  133.                 currByte = 10 + currByte;
  134.                 shift = 1;
  135.             }
  136.             else shift = 0;
  137.             result = currByte.toString() + result;
  138.         }
  139.         return sign + clearZero(result);
  140.     }
  141.    
  142.     //умножение
  143.     function multiply(op1, op2)
  144.     {
  145.         var result = '';
  146.        
  147.         for(var i = op2.length - 1; i >= 0; i--)
  148.         {
  149.             //перенос из младшего разряда в старший
  150.             var shift = 0;
  151.             //промежуточный результат - умножение первого операнда на очередную цифру второго
  152.             var currRow = '';
  153.            
  154.             for(var j = op1.length - 1; j >= 0; j--)
  155.             {
  156.                 //считаем текущий разряд
  157.                 var currByte = parseInt(op1.charAt(j)) * parseInt(op2.charAt(i)) + shift;
  158.                 shift = currByte / 10 | 0;
  159.                 currByte = currByte % 10;
  160.                 currRow = currByte.toString() + currRow;
  161.             }
  162.             if(shift != 0)
  163.                 currRow = shift.toString() + currRow;
  164.             //нулями в конце осуществляем сдвиг при сложении результатов суммирования отдельных строк
  165.             currRow = addZeroToEnd(currRow, op2.length - 1 - i);
  166.             result = adding(result, currRow);
  167.         }
  168.         return result;
  169.     }
  170.    
  171.     //деление
  172.     function divide(op1, op2)
  173.     {
  174.         var result = '';
  175.        
  176.         //сначала сравним операнды: если делитель больше делимого, то результат будет нулём
  177.         if(compare(op1, op2) < 0) return '0';
  178.        
  179.         //промежуточная разность для перехода между итерациями деления
  180.         var shift = '';
  181.         //промежуточное уменьшаемое на каждой итерации
  182.         var currOp1 = op1.substr(0, op2.length);
  183.         op1 = op1.substr(op2.length);   //отрезаем от уменьшаемого взятые символы, чтобы не мешались
  184.         while(true) //условие исправить!
  185.         {
  186.             //ищем очередной разряд частного - для этого перебираем все цифры от 9 до 1
  187.             //на ноль проверим отдельно, чтобы не гонять цикл с умножением
  188.             if(compare(currOp1, op2) < 0)
  189.             {
  190.                 shift = currOp1;
  191.                 result = result + '0';
  192.             }
  193.             else
  194.                 for(var i = 9; i > 0; i--)
  195.                 {
  196.                     var currOp2 = multiply(op2, i.toString());
  197.                     if(compare(currOp1, currOp2) >= 0)
  198.                     {
  199.                         shift = substract(currOp1, currOp2);
  200.                         result = result + i.toString();
  201.                         break;
  202.                     }
  203.                 }
  204.            
  205.             if(op1.length == 0) break;  //граничное условие
  206.             //после итерации добавляем к промежуточному уменьшаемому ещё один разряд
  207.             currOp1 = shift + op1[0];
  208.             op1 = op1.substr(1);
  209.         }
  210.        
  211.         return clearZero(result);
  212.     }
  213.    
  214.    
  215.     //заполнение строки начальными нулями
  216.     function addZeroToBegin(str, count)
  217.     {
  218.         for(i = 0; i < count; i++)
  219.             str = '0' + str;
  220.         return str;
  221.     }
  222.  
  223.     //заполнение строки конечными нулями
  224.     function addZeroToEnd(str, count)
  225.     {
  226.         for(i = 0; i < count; i++)
  227.             str = str + '0';
  228.         return str;
  229.     }
  230.  
  231.     //удаление начальных нулей из строки
  232.     function clearZero(str)
  233.     {
  234.         for(i = 0; i < str.length; i++)
  235.         {
  236.             if(str[i] != '0')   //пока не найдём первый ненулевой символ
  237.             {
  238.                 str = str.substr(i);    //запоминаем всю строку, начиная с него
  239.                 return str;
  240.             }
  241.         }
  242.         //на случай, если вся строка состоит из нулей
  243.         if(str[str.length-1] == '0') return '0';
  244.        
  245.         return str; //если ничего не нашли
  246.     }
  247.    
  248.     //функция сравнения длин двух операндов
  249.     //возвращает 1, если op1 > op2, -1, если op1 < op2, и 0, если равны
  250.     function compare(op1, op2)
  251.     {
  252.         if(op1.length > op2.length) return 1;
  253.         if(op1.length < op2.length) return -1;
  254.         //если число знаков равно, то ищем до первого несовпадающего
  255.         if(op1.length == op2.length)
  256.             for(var i = 0; i < op1.length; i++)
  257.             {
  258.                 if(op1[i] > op2[i]) return 1;
  259.                 if(op1[i] < op2[i]) return -1;
  260.             }
  261.         return 0;
  262.     }
  263. </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement