Javascript toFixed方法未按中的预期工作

Javascript toFixed方法未按中的预期工作,javascript,angularjs,Javascript,Angularjs,在处理大量数据时,我发现了一些奇怪的问题 (99999999999999.9).toFixed(2) returns "99999999999999.91" 何处为 (99999999999999.8).toFixed(2) returns "99999999999999.80" 我需要的是 (99999999999999.9).toFixed(2) should return "99999999999999.90" 如何解决此问

在处理大量数据时,我发现了一些奇怪的问题

(99999999999999.9).toFixed(2) returns "99999999999999.91"
何处为

(99999999999999.8).toFixed(2) returns "99999999999999.80"
我需要的是

(99999999999999.9).toFixed(2) should return "99999999999999.90"

如何解决此问题?

您肯定遇到了浮点精度错误。 如果您的特定用例不需要特别敏感,您可以使用

(Math.round(yourValue*100)/100).toFixed(2)
还有一种更新的处理方法,使用

特别是玩分数

   minimumFractionDigits: 2,      
   maximumFractionDigits: 2
当然,若你们需要一些更健壮的,能够很好地处理其他边缘情况的,也可以提供帮助

var a = new Decimal(99999999999999.9);
console.log(a.toFixed(2))

在这里,您肯定遇到了浮点精度错误。 如果您的特定用例不需要特别敏感,您可以使用

(Math.round(yourValue*100)/100).toFixed(2)
还有一种更新的处理方法,使用

特别是玩分数

   minimumFractionDigits: 2,      
   maximumFractionDigits: 2
当然,若你们需要一些更健壮的,能够很好地处理其他边缘情况的,也可以提供帮助

var a = new Decimal(99999999999999.9);
console.log(a.toFixed(2))

您基本上无法做到这一点,这是由于数字在浮点中的表示以及javascript在后台的工作方式:

Javascript用于表示内存中的符号9999999999显示为

0 10000101101 0110101111001100010000011110100011111111111111111010
这是一个由3个整数部分组成的数字:

首先,符号0表示它是正的

然后是指数乘数-1069。我们从中减去1023以允许负指数,因此乘数为'2^1069-1023

然后是尾数-data-1.421085471520199wikipedia上显示的计算没有mathjax,这有点难以显示

因此,根据wolfram alpha 9999999999999.903472220635136,总值为+1.421085471520199*2^1069-1023=

正如你所看到的,它不能精确地显示十进制精度。这是由于尾数有限,我们可以看到,如果我们更改尾数的最后一位,则高出1会得到9.999999999245828438884352×10^13。下面的一个是9.99999999998893984717996032×10^13

因此,9.99999999998893984717996032×10^13和9.999999999999993472220635136×10^13之间的所有内容都表示为相同的数字-您不会注意到其中的差异。[*]

至于为什么在本例中再次显示浮点时会向上取整:这有点难以解释,但我想这是由于实现的原因

现在我们能预测这个吗?为什么它不是十进制的呢?这很容易解释。一个数字系统有不同的基数,通常我们使用基数10,而计算机使用基数2作为内在单位

这个选择有着牵强的后果:当在某个基数中工作时,你只能表示该基数的基本因子的倍数的分数。IE基数10有基本因子2和5。所以我们可以显示任何分数,它是这些分数的倍数:

1/2 => 0.5
1/5 => 0.2 
2/5 => 0.4 
1/10 = 1/2*1/5 => 0.1
然而,1/3不能被描述为这两个分数的倍数,也不能被描述为1/7或1/6——因此在10进制中,我们不能准确地将它们写成小数

类似地,基2只有素数因子2。以“.9”结尾的数字在十进制中始终是基于1/5的分数,它不是二进制的一部分-因此不能用二进制描述

现在有了解决方案,通常存在提供所谓的十进制软件包的库,这些软件包以十进制表示数字,并用手动计算取代内部计算机FPU


[*]:ps我不知道它是否真的是这些边界-因此浮点解释器是否总是向上取整,或者解释器是否向最近的浮点取整。了解JS解释器的人可以回答这个问题。

你基本上无法做到这一点,这是因为数字在浮点中的表示以及javascript在后台的工作方式:

Javascript用于表示内存中的符号9999999999显示为

0 10000101101 0110101111001100010000011110100011111111111111111010
这是一个由3个整数部分组成的数字:

首先,符号0表示它是正的

然后是指数乘数-1069。我们从中减去1023以允许负指数,因此乘数为'2^1069-1023

然后是尾数-data-1.421085471520199wikipedia上显示的计算没有mathjax,这有点难以显示

因此,根据wolfram alpha 9999999999999.903472220635136,总值为+1.421085471520199*2^1069-1023=

正如你所看到的,它不能精确地显示十进制精度。这是由于尾数有限,我们可以看到,如果我们更改尾数的最后一位,则高出1会得到9.999999999245828438884352×10^13。下面的一个是9.99999999998893984717996032×10^13

因此,9.99999999998893984717996032×10^13和9.999999999999993472220635136×10^13之间的所有内容都表示为相同的数字-您不会注意到其中的差异。[*]

至于为什么在本例中再次显示浮点时会向上取整:这有点难以解释,但我想这是由于实现的原因

现在可以 我们能预测吗?为什么它不是十进制的呢?这很容易解释。一个数字系统有不同的基数,通常我们使用基数10,而计算机使用基数2作为内在单位

这个选择有着牵强的后果:当在某个基数中工作时,你只能表示该基数的基本因子的倍数的分数。IE基数10有基本因子2和5。所以我们可以显示任何分数,它是这些分数的倍数:

1/2 => 0.5
1/5 => 0.2 
2/5 => 0.4 
1/10 = 1/2*1/5 => 0.1
然而,1/3不能被描述为这两个分数的倍数,也不能被描述为1/7或1/6——因此在10进制中,我们不能准确地将它们写成小数

类似地,基2只有素数因子2。以“.9”结尾的数字在十进制中始终是基于1/5的分数,它不是二进制的一部分-因此不能用二进制描述

现在有了解决方案,通常存在提供所谓的十进制软件包的库,这些软件包以十进制表示数字,并用手动计算取代内部计算机FPU


[*]:ps我不知道它是否真的是这些边界-因此浮点解释器是否总是向上取整,或者解释器是否向最近的浮点取整。有JS解释器知识的人可以回答这个问题。

可能您遇到了浮点精度错误?是的,这是一个财务应用程序,即使是1个paise也会产生差异。如果您需要这种精度,我建议使用库。JS本身不合适请推荐一些库您在下面的答案中已经有了建议?可能您遇到了浮点精度错误?是的,这是一个财务应用程序,即使是1个paise也会产生差异如果您需要此精度级别,我建议使用库。JS本身不合适请建议一些库您在下面的答案中已经有了建议?Math.round99999999999.9*100/100.toFixed2返回99999999999999.91 Decimal.JS好吗?Math.round99999999999999999.9*100/100.toFixed2返回99999999999999.91 Decimal.JS好吗?