Javascript添加给我一个超过2位小数的输出

时间:2014-12-01 07:54:50

标签: javascript mysql

我的对象在mySql上有一个money属性,数据类型为Decimal(10,2)。

我的javascript生成一个http请求来检索这些值,我处理我的javascript函数中的数据,将所有值加到一个$ scope中:

 $scope.expected = 0;
 for(var k = 0; k < collection.length; k++)
    {
        $scope.expected += Number(collection[k].price);
    }

price是包含125.89作为DB值的货币值。迭代进行了31次迭代,collection.length返回31

我使用Number参考,因为它以字符串开头。

当循环结束时,我最终得到这个总和:3902.589999999999但我想要的只是3902.58,因为这是金钱,它必须是一个精确的表示。我研究过,社区似乎同意使用toFixed(2),但根据我的理解,toFixed(2)将数字向上舍入,这是我不想做的事情,因为此操作涉及现金。

有没有办法保留2位小数而不进行舍入?

我还在整个循环中保存了console.log的日志。结果如下:

125.89
251.78
377.67
503.56
629.45
755.34
881.23
1007.12
1133.01
1258.9
1384.7900000000002
1510.6800000000003
1636.5700000000004
1762.4600000000005
1888.3500000000006
2014.2400000000007
2140.1300000000006
2266.0200000000004
2391.9100000000003
2517.8
2643.69
2769.58
2895.47
3021.3599999999997
3147.2499999999995
3273.1399999999994
3399.0299999999993
3524.919999999999
3650.809999999999
3776.699999999999
3902.589999999999

3 个答案:

答案 0 :(得分:0)

我在这里为您的问题创建了代码:

for(var k = 0; k < data.length; k++)
{
    var num2 = data[k].toString().split('.');
    if(typeof num2[1] != 'undefined')
    {
        num2[1] = num2[1].toString().substring(0,2);
        data[k] = num2[0] + "." + num2[1];
    }
    console.log(Number(data[k]));
}

Have a Look at Fiddle

答案 1 :(得分:0)

从你的帖子中可以看出你正在处理正数。

如果要截断最终结果,可以通过调用Math.floor来实现这一目标

$scope.expected = Math.floor($scope.expected * 100)/100;

但是,另一方面,如果你想在求和之前将每个数字截断为两位小数,那么你可以使用以下

$scope.expected = 0;
 for(var k = 0; k < collection.length; k++)
    {
        $scope.expected += Math.floor(Number(collection[k].price) * 100) / 100;
    }

请注意,这仅适用于所有数字均为正数(大于或等于零)的情况。

如果你期望负数,你可以设计如下函数:

truncateNumber = function (number) {
    if(number < 0){
       return Math.ceil(number * 100) / 100;
    }else{
       return Math.floor(number * 100) / 100;
    }   
};

示例

使用

 $scope.expected = truncateNumber($scope.expected);

  for(var k = 0; k < collection.length; k++)
   {
        $scope.expected += truncateNumber(Number(collection[k].price));
   }

答案 2 :(得分:0)

由于浮点数在javascript中的工作方式,您所描述的行为是可以预期的。您需要的解决方案取决于您需要的准确范围:如果您需要更大的数字范围,那么您可以使用javascript获取,您应该查看一个大数字库。

因为Math.pow(2, 53) === 9007199254740992是javascript中可以直接表示的最大整数,所以可以将该范围减小100倍,从而在准确度上获得2位小数。这将使你的正范围[0,90071992547409]。

我认为你不想3902.58;你可能想要:3902.59(= 125.89 * 31)

假设您的输入的最大精度为2位小数且没有负值:

&#13;
&#13;
<xmp id="dbg"></xmp>
<script>// create $scope, collection and get debug output element for example:
for(var dbg=document.getElementById('dbg'), $scope={}, L=31, collection=new Array(L); L--; collection[L]={price:'125.89'});

// ==========  ANSWER BEGINS HERE:  ==========

$scope.expected = 0;
for(var k = 0; k < collection.length; k++){
   $scope.expected += Number(collection[k].price)*100;  //increase precision
   //added debug line meant to resemble the debug listing in your question:
   dbg.innerHTML+=($scope.expected / 100).toFixed(2) + '\n' ;
}
// maintain precision internally and only round when needed (like before output)
// flooring your total is optional (not needed when you can guarantee 
//   no more than 2 decimals at the input-side). 
// divide by 100 before output
// then use toFixed to convert the number to string 
//   AND append dot/decimals when needed 
dbg.innerHTML+='\nTotal: ' + (Math.floor($scope.expected) / 100).toFixed(2);
</script>
&#13;
&#13;
&#13;

不要被toFixed抛弃:我们使用它来确保2位小数(换句话说,添加尾随0&#39; s(如果需要,还有一个点)对于8.84

等数字的分数