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