js发展那么多年了,为什么都不去解决这个问题呢?
如果说无法解决,有人能简单说明一下为什么无法解决这样的问题吗?
是时候那祭出大神的网站了,里边有详细的原因说明。
http://0.30000000000000004.com
域名难记?随便一个c系(php、java、c、c++、javascript)语言,计算一下就可以了。
js代码:
location.href = 'http://' + (0.1+0.2) + '.com';
程式语言内建对于浮点数的精度问题。这个问题我不是专家,但可以分享一些看法。
首先你要理解几点,在JavaScript语言中的数值(Number)类型是什么?它也只有一种数值的类型,没有整数、浮点数、双精度浮点数的设计。标准上是说这数值(Number)类型,是使用双精度浮点数(double)使用64位元(8位元组)的设计,但是在引擎的内部实作实际上它会知道是什么也会区分,为什么要区分,理由当然就是为了执行时的效率与资源使用。
高精度浮点数的数学运算是有代价的,只有在某些情况下,我们会需要高精度浮点数的数学运算,或是非常多位数的数学运算,通常是在科学上的运算。JavaScript语言的设计本身就不是为了这些运算而设计的,它是个动态类型的脚本语言,而且一开始是在有限的浏览器环境下才能执行。
当然,你也可以说,像这么简单的0.3 - 0.1
或0.2 + 0.1
都算不好,这算那门子程式语言,不见得用什么高超的例子来测试,这两个例子就可以看得到。这也不算JavaScript本身的问题,许多程式语言中都有类似的问题,
听过python吧,下面是python中0.2 + 0.1
的结果:
>>> 0.1 + 0.2
0.30000000000000004
听过ruby吧,下面是ruby中0.2 + 0.1
的结果:
puts 0.1 + 0.2
0.30000000000000004
上面两个脚本语言可能没用过,那么Java大牛应该有听过了,下面是Java中0.2 + 0.1
的结果:
System.out.print(0.1+0.2);
0.30000000000000004
当然,我上面举的例子只是未经过再进一步定义资料类型的例子,不同的程式语言有不同的资料类型定义,用于处理高精度数字的问题。这些例子还可以举出很多,目的是要说明JavaScript并非是想像中那么设计不良的程式语言,拿你的例子去套到这些程式语中,也是类似的情况。所以,并不是所谓发展这么久了,不求上进的问题,而是这个问题存在了很久,它自然有别的方式来解决这些问题,下面再来谈谈如何面对与解决这些问题。
第一种方式是类型,在js中不像其他程式语言有内附的高精度数字类型,所以你需要扩充,函式库很多可以参考使用,BigDecimal、decimal.js、big.js等等,为什么我讲类型而不是单个物件或函式库而已,因为高精度的数字运算,大概都不能再使用你原先使用于数字的+-*/%
符号来运算,而是要用整个类型所能提供的方法,额外作运算才行。这整个函式库都是在考量效率、资源的消耗等等。当然他们也有计算的极限,不可能能计算永无止尽的数字位数。这个方式适合你真的需要科学上的、金钱上的(例如算股票、利息之类),或是真的是高精度的数字运算。
第二种方式是格式化你的运算结果,如果这能达成你的需求的话,例如你只需要小数点后两位,那么可以用格式化的方法来呈现即可,至少一般简单的运算是可行的。
第三种就是不要用浮点数,只用整数值。四舍五入也是一种解决方案,能预测的准的话也可以自己看需求写函式来求值。整数值可以让你的开发日子更轻松美好,整数值对js引擎来说,其实是飞快的。
如果你对浮点数想要进一步理解,或是看各种程式语言中的基本解决方了,我会推荐看这篇: http://floating-point-gui.de/或是它的github: https://github.com/brazzy/flo...
8 回答4.3k 阅读✓ 已解决
6 回答2.7k 阅读✓ 已解决
5 回答2.4k 阅读✓ 已解决
5 回答6.1k 阅读✓ 已解决
4 回答2.1k 阅读✓ 已解决
3 回答2.3k 阅读
4 回答2.6k 阅读✓ 已解决
https://segmentfault.com/a/11...
事实上把全宇宙的硬盘加起来也存不了0.1的二进制。