Java--float浮点数类型精度问题 Bertha 。 2021-11-16 16:02 327阅读 0赞 ## 浮点数为什么不精准? ## 参考链接:[https://blog.csdn.net/renwotao2009/article/details/51637163][https_blog.csdn.net_renwotao2009_article_details_51637163] 我们在计算机中写的十进制小数,只有 0 和 1 的计算机要怎么处理? 我们来试一试如何表达十进制的 0.2 吧。 0.01 = 1/4 = 0.25 ,太大 0.001 =1/8 = 0.125 , 又太小 0.0011 = 1/8 + 1/16 = 0.1875 , 逼近0.2了 0.00111 = 1/8 + 1/16 + 1/32 = 0.21875 , 又大了 0.001101 = 1/8+ 1/16 + 1/64 = 0.203125 还是大 0.0011001 = 1/8 + 1/16 + 1/128 = 0.1953125 这结果不错 0.00110011 = 1/8+1/16+1/128+1/256 = 0.19921875 已经很逼近了, 就这样吧。 这就是为什么二进制无法准确表达十进制小数。 我们知道像byte、short、int、long整型类型的数据,他们存储的时候就是整数转化为二进制存储的,是多少就是多少,拿byte类型举例:一个byte类型的数据占一字节(1B)即八位,所以的它的范围就是:-2^7~2^7-1 而浮点数类型float,它占4个字节(4B)即32位,按理说它的取值范围应该是:-2^31~2^31-1,但是它真正的取值范围却约等于:-3.4E38~3.4E38,接下来我们就要研究一下浮点数类型在计算机中是怎么存储的。 拿 0.09f 为例: long l = Float.floatToRawIntBits(0.09f); System.out.println(long.toBinaryString(l)); 输出结果: 111101101110000101000111101100 我们在它的前面补 0 ,补足32位,按照 1 符号位,8 阶码位,23 尾数位分开。 0 01111011 01110000101000111101100 你可以看到其实它分为了三段: * 第一段代表了符号(s) : 0 正数, 1 负数 , 其实更准确的表达是 (-1) ^0 * 第二段是阶码(e):01111011 ,对应的10进制是 123 * 第三段是尾数(M) 你看到了尾数和阶码,就会明白这其实是所谓的科学计数法: (-1)^s \* M \* 2^e 但是把数代进去会发现: (-1)^0 \* 01110000101000111101100 \* 2^123 这显然要比 0.09f 要大的很多 这是因为浮点数遵循的是IEEE754 表示法, 我们刚才的s(符号) 是对的,但是 e(阶码)和 M(尾数)需要变换: 对于阶码e , 一共有8位, 这是个有符号数, 特别是按照IEEE754 规范, 如果不是0或者255, 那就需要减去一个叫**偏置量**的值,对于float 是127 所以 E = e - 127 = 123-127 = -4 对于尾数M ,如果阶码不是0或者255, 他其实**隐藏了一个小数点左边的一个 1** (节省空间,充分压榨每一个bit啊)。 即 M = 1.01110000101000111101100 现在写出来就是: 1.01110000101000111101100 \* 2^-4 (二进制的运算就是小数点往前移 4 位) =0.000101110000101000111101100 = 1/16 + 1/64 + 1/128+ 1/256 + …. = 0.0900000035762786865234375 你看这就是0.09的内部表示, 很明显他比0.09更大一些, 是不精确的! 我们再拿一个比较大的数举例子,24625125f : float fl = 24625125f; 输出结果: 2.4625124E7 最后一位 5 竟然变成了 4?! 按照float遵循的IEEE754表示法,我们先输出一下它的二进制(补全32位)表示: 0 10010111 01110111101111111110010 同理按照上面的步骤再计算一次: E = e - 127 = 151 - 127 = 24 M = 1.01110111101111111110010 计算: 1.01110111101111111110010 \* 2^24 =1011101111011111111100100 =2^24+2^22+2^21+2^20+ .... =24,625,124 这就是存储到计算机中的二进制再转换为十进制的时候,会丧失精度原因。 这样我们在用float处理金融方面的问题,或者需要特别高精度的时候就不能使用float、double浮点数类型了。 [https_blog.csdn.net_renwotao2009_article_details_51637163]: https://blog.csdn.net/renwotao2009/article/details/51637163
相关 Java浮点数运算精度问题示例 在Java中,浮点数的运算可能会出现精度问题。这主要是因为Java使用IEEE 754标准来表示和处理浮点数。 以下是一个简单的例子,展示了浮点数运算可能存在的精度问题: 今天药忘吃喽~/ 2024年09月10日 15:54/ 0 赞/ 30 阅读
相关 单精度浮点数和双精度浮点数_浮点数和双精度数之间的区别 ![0b4d070881144d90e79ec876b69711aa.png][] 单精度浮点数和双精度浮点数 Here you will learn about diff 朴灿烈づ我的快乐病毒、/ 2022年12月07日 13:29/ 0 赞/ 204 阅读
相关 Java浮点数精度控制 package mypackage; import java.text.DecimalFormat; public class NumberTest \{ public sta 分手后的思念是犯贱/ 2022年09月28日 13:23/ 0 赞/ 188 阅读
相关 浮点数精度问题处理 [参考][Link 1] 由于浮点数在计算机中的存储问题,所以不论是float类型的数据还是double类型的数据都是有其精度的,取浮点数精度下限,float为6位,doub 逃离我推掉我的手/ 2022年08月10日 10:56/ 0 赞/ 202 阅读
相关 浮点数输入精度问题 输入: ![Image 1][]![Image 1][]![20150814202153285][] ![20150814202156072][] ![201508 你的名字/ 2022年08月04日 00:59/ 0 赞/ 203 阅读
相关 C++ Primer 学习笔记:浮点数精度问题 之前做过LFF Solver的时候遇到了浮点数的精度问题,因为浮点数计算到一定的精度之后的计算结果就全靠运气了。 这个本身是由于浮点数本身是按照科学计数法来存储的,在坐标轴上 喜欢ヅ旅行/ 2022年06月02日 02:06/ 0 赞/ 164 阅读
相关 JS浮点数精度缺失问题 先看一个例子 alert(0.7+0.1);//输出0.7999999999999999 alert(0.6+0.2);//输出0.8 第二个正确,但第一个 曾经终败给现在/ 2022年04月11日 14:45/ 0 赞/ 250 阅读
相关 Java--float浮点数类型精度问题 浮点数为什么不精准? 参考链接:[https://blog.csdn.net/renwotao2009/article/details/51637163][https_b Bertha 。/ 2021年11月16日 16:02/ 0 赞/ 328 阅读
相关 JavaScript 浮点数运算的精度问题 问题描述 在 `JavaScript` 中整数和浮点数都属于 `Number` 数据类型,所有数字都是以 `64` 位浮点数形式储存,即便整数也是如此。 所以我们在打印 ╰半夏微凉°/ 2021年07月04日 21:43/ 0 赞/ 411 阅读
还没有评论,来说两句吧...