如何在Javascript中进行乘法运算?小数问题解决方案

40

我有以下 Javascript 代码:

var m1 = 2232.00;
var percent = (10/100);
var total = percent*m1;
alert(total);

问题在于变量“total”给出的值是“223.20000000000002”,但它应该是“223.2”,我该怎么做才能得到正确的值?


5
这可能是您正在寻找的答案:https://dev59.com/tXM_5IYBdhLWcg3wQQpd - Dimitry
有关在JavaScript中四舍五入数字的更多信息,请参见https://dev59.com/WHVC5IYBdhLWcg3wlyMo - radical7
1
可能是重复的问题:浮点数运算是否存在问题? - user180100
14个回答

31

.toFixed()是最好的解决方案。它会保留小数点后两位数字。

示例1:

var value = 3.666;
value.toFixed(2); //Output : 3.67

实验2:

var value = 3.0000;
value.toFixed(2); //Output : 3.00

5
注意,.toFixed(n)的结果是一个字符串而不是十进制数值...因此使用++=会将其连接在一起,而不是加到变量中。 - freefaller

8

浮点数的一个基本问题是精确值难以获得。

您可以使用toFixed强制保留固定数量的小数位:

alert(total.toFixed(2));

然而,请记住这会留下尾随的零,这可能不是你想要的。您可以使用.replace(/0+$/,'');来删除它们。


你可能还希望在.replace(/0+$/, '')之后再加上.replace(/.$/, ''),以便在有小数点的情况下清除任何尾随的小数点。 - lamplightdev
.replace(/.$/, '') 不起作用,请尝试使用 .replace(/\.$/, '') - Alpha Wolf Gamer

7
如果您想显示这个数字,您可以使用toFixed(1)将其转换为字符串。如果这样做,请注意类型,因为您不能将字符串与另一个数字相乘。
如果您要在其他计算中使用它,则可以将其截断为一位小数:
Math.round( total * 10 ) / 10

然而,正如一些人指出的那样,不精确的值只是浮点数的一种表现方式。

有关更多优秀信息,请查看评论中链接的问题。


事实上,我不需要将这个值转换为字符串,因为我需要使用变量“total”与另一个变量相乘。 - gustavomanolo
你可以放心地这样做。这是JS中浮点数的方式,MSVC++中也是float或double。 - Kitet

5

运算符“*”和“/”并不总是完美工作的,例如:

32.09 * 100 = 3209.0000000000005
100 / (1 / 32.09) = 3209.0000000000005

解决方案:

一个常见的解决方案是使用.toFixed(2)获取小数,其中“2”是你需要的小数位数。但要注意这会返回一个字符串,并且会对值进行四舍五入。

45.6789.toFixed(2) —> "45.68" as String

另一个选择是使用 .toLocaleString,在转换数字时将其正确地转换为所需的国家代码。您可以设置一对参数,始终将小数值固定为2。这还会返回一个字符串:

(654.3453).toLocaleString(
  'en-US',
  {minimumFractionDigits: 2, maximumFractionDigits: 2},
) —> "654.35" as String

如果你需要将它作为数字使用,你可以将它包装成Number(...):

Number((654.3453).toLocaleString(
  'en-US',
  {minimumFractionDigits: 2, maximumFractionDigits: 2},
)) —> 654.35 as Number

如果您只想要一个没有小数的数字,请使用以下任一方法确保结果没有小数。

Math.trunc(32.09); —> 32 as Number  
(32.09).toFixed(0); —> “32” as String
32.09 | 0; —> 32 as Number

5

bignumber.js现在已经在jsdelivr CDN上了。 - Xotic750

3
我最终得出了以下解决方案:
function decimalmultiply(a, b) {
    return parseFloat((a * b).toFixed(12));
}

10.50*30.45=319.72499999999997
decimalmultiply(10.50,30.45)=319.725

这个方法返回一个数字,而不是字符串,不会截断有效的小数位(最多12位)。


3

total.toFixed(2) 可能会有帮助。但请注意,total 变量将被强制转换为字符串类型。


https://dev59.com/G3RB5IYBdhLWcg3wj36c - srijan

3

这可以使用一个名为decimal.js的外部库来完成,该库为JavaScript提供了一种Decimal类型。它也可在npm上用于Node。下面是一个示例,它使用decimal.js复制了gustavomanolo的原始示例。

// Decimal type provided by decimal.js (http://mikemcl.github.io/decimal.js/)
var m1 = new Decimal( 2232.00 );
var percent = new Decimal( 10/100 );
var total = m1.mul(percent);
console.log( 'Total:', total );
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/7.2.3/decimal.min.js"></script>


2

这里有一个浮点数乘法的解决方案。它非常简单,但对我来说有效。您可以使用此函数计算数字具有的小数位数。

function decimalPlaces(num) {
    var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
    if (!match) { return 0; }
    return Math.max(
        0,
        // Number of digits right of decimal point.
        (match[1] ? match[1].length : 0)
        // Adjust for scientific notation.
        - (match[2] ? +match[2] : 0));
}

然后,对于您的最终答案“total”,您可以这样做
total = total.toFixed(decimalPlaces(a)+decimalPlaces(b));

a,b为你的数字


感谢 Mike Samuel 在帖子 [链接] (https://dev59.com/OWkv5IYBdhLWcg3wpCXJ) 中提供 decimalPlaces 函数。 - PetrosM

1

只是尝试

var x = 0.07;
console.log((x+1)*100 - 100);

现在,将x的值替换为其他值即可;-)。

它不能正常工作,例如取x = 0.041。 - Abhi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接