脑壳疼,测试段代码需要用到个算式 : 19.99 * 100 - 1999,结果为-2.2737367544323E-13;
算式中的 19.99 可以以变量形式传递进来,也还是这个结果. 用 19.98100-1998(或其他两位小数的数字减去它乘 100 的数字) 都正常为 0.
算式在 java php js 中都为这个结果,感觉 19.99 好诡异,各位前辈有遇到过这样的情况么,有没有好的解决方案来避免.目前我的测试是用命令(php) sprintf("%.0f", 19.99100)才能正常执行..
(咦~好奇怪,上面这段文本突然斜体了...)
1
limuyan44 2019-07-22 18:33:11 +08:00 via Android 1
java 中有专门用于高精度计算的类型,php 料想应该也有,通常涉及浮点型本身就是近似计算。
|
2
ipwx 2019-07-22 18:36:19 +08:00 1
月经问题。。。
内存中浮点数是二进制存储的。一个有限十进制小数不一定存在对应的有限二进制小数。事实上除了能写成“某个整数 + sum_{i=1}^k a_i 2^{-i}”这种形式的小数,都不能写成有限的二进制小数。 而计算机的浮点数有长度限制,一个无限循环二进制小数截断以后,就和原来的十进制小数并不完全相等了。你减出来的这个值,就是截断误差。 |
3
johnniang 2019-07-22 18:38:01 +08:00 via Android 1
建议看看 《计算机组成原理》。
|
4
Rekkles 2019-07-22 18:38:39 +08:00 1
php 请用 bcmath
echo bcsubbcmul(19.99,100,2),1999); |
5
Raymon111111 2019-07-22 18:59:56 +08:00 1
简单讲
你看见的 19.99 十进制下人畜无害, 有可能在二进制下是一个无限循环小数 (可以自己做一下进制转换) 这样一来, 就算乘以 100 和后面的数相减也得不到 0 |
6
ClericPy 2019-07-22 19:15:33 +08:00 1
搜一下 浮点数 IEEE
|
7
laodao1990 2019-07-22 19:24:25 +08:00 1
推荐看看《深入理解计算机系统》
通俗点解释就是,计算机是用二进制表示的,对于某些小数和人类用 10 进制无法准确表示 1/3 是一个意思,会有误差。 |
8
VDimos 2019-07-22 19:31:01 +08:00 via Android 1
真—月经问题
|
9
Kirscheis 2019-07-22 19:40:06 +08:00 via Android 3
f64(19.99) = 0x1.3fd70a3d70a3dp+4
f64(100.0) = 0x1.9000000000000p+6 0x1.3fd70a3d70a3dp+4 * 0x1.9000000000000p+6 = 0x1.f3bffffffffffp+10 f64(1999.0) = 0x1.f3c0000000000p+10 所以结果是 0x1.f3c0000000000p+10 - 0x1.f3bffffffffffp+10 = -0x1.0000000000000p-42 转换到 10 进制就是 -2.2737367544323206e-13 |
10
Kirscheis 2019-07-22 19:41:34 +08:00 via Android
上面打多一个负号,凑合看
|
11
joshu 2019-07-22 19:42:01 +08:00 via Android 1
浮点数的比较一般是小于 1e-N ( N 多少我忘了)就视为相等
不要比较浮点数相等 |
12
akazure 2019-07-22 19:42:40 +08:00 via Android 1
一般采取新建一个 equal 方法,并定义一个极小量,以作为误差范围。
|
13
jamesliu96 2019-07-22 19:43:11 +08:00 via Android 1
IEEE 754
|
14
Mistwave 2019-07-22 19:48:20 +08:00 via iPhone 1
|
15
littlewing 2019-07-22 19:50:19 +08:00 1
手动搜索 “ IEEE754 浮点数”
|
16
heart4lor 2019-07-22 20:29:37 +08:00 1
浮点数存储问题都不知道的么,斜体是因为 markdown 语法
|
17
xuanbg 2019-07-22 20:41:34 +08:00 1
一般的业务场景有小数的时候不要用浮点数,不要用浮点数,不要用浮点数。重要的事情说 3 遍。因为我们默认计算的结果是精确的,而浮点数是有精度问题的,不能满足精确的要求。
|
18
msg7086 2019-07-22 23:27:42 +08:00 1
小数通常是近似值不是精确值。
|
19
TobiahShaw 2019-07-23 09:48:37 +08:00 1
因为不连续,你可以判断 19.99 * 100 - 1999 < Epsilon,或者使用 BigDecimal
|
20
brust 2019-07-23 14:27:28 +08:00 1
精度问题 浮点数 计算会丢失精度
java 的话推荐<码出高效>这本书 |