既然浮点数据类型不精确,那么浮点数存在的意义在哪?

2021-03-18 14:20:45 +08:00
 xiaokongwu

既然二进制无法精确的表示小数,那么为什么设计浮点数(float/double)这种不精确的格式,而不直接设计一种基础的,可以精确表示小数的基础数据类型呢?

IEEE 虽然规定了浮点数的格式,但这种浮点数格式仍然是不精确的,为什么不直接规定一种精确的存储格式呢? 比如整数小数分开存储,前 N 位是整数,后 N 位是小数,再来几位存 scale/precision 之类的设计,就像 Java 里的 BigDecimal 一样

9823 次点击
所在节点    Java
83 条回复
raptor
2021-03-19 09:25:54 +08:00
楼主基本功不行啊,这么基础的常识都不理解。

计算机组成原理难道不是最基本的课程之一么?
passerbytiny
2021-03-19 09:32:31 +08:00
不晚于高中,数学就会教你无限不循环小数、虚数,意即为“随着认知的扩大,完全精确的数是不存在的”。大学里面数学专业的高等代数 /数学分析,会教你迭代求(无限逼近但无法精确的)值,意即为“随着认知的扩大,完全精确的计算是不可能的”。而初中物理开篇之后第二堂课就是讲“误差”。

以上回答不会对楼主现在的问题解惑,但会对楼主为什么不该提这个问题解惑。
lz0755
2021-03-19 09:37:29 +08:00
你去看计组就明白了
pkoukk
2021-03-19 09:52:25 +08:00
开销问题啊,一般常用范围内的小数运算用 float 是没有问题的。a=0.3x0.2,print(a),我相信常见语言返回的都是 0.06000
只是不建议用==进行比较而已,你非要比其实也没问题,据我所知很多语言编译时都会自动优化。
zealinux
2021-03-19 10:00:41 +08:00
```clojure
(/ 3 9)
;; => 1/3


(double 1/3)
;; => 0.3333333333333333
```

可以使用有理数(分数形式),
所有中间计算全部用分数,
然后最后的结果再转化成浮点数,
这样能保证全部中间计算不丢失任何精度。
cigarzh
2021-03-19 10:25:53 +08:00
二进制信息是离散的
实数是稠密而连续的
理论是无穷的
现实是有限的

没有完美的方法 能解决实际问题就是意义
Cu635
2021-03-19 10:44:46 +08:00
@whileFalse
说反了,是需要计算圆的周长和体积,发现周长除以直径是个常数记为 pi,然后才发现并且证明 pi 是个无理数。

@cigarzh
应该说有限位的二进制信息是离散的。
nicebird
2021-03-19 11:20:48 +08:00
浮点数的目的就是为了小数位浮动,换取更大的表示范围。
需要固定小数位的实现定点数就行了。
siyemiaokube
2021-03-19 11:33:07 +08:00
与精度有限的数值计算相对地,我们称作“符号计算”。

实际上可以实现以分数形式储存有理数。在这种意义下,分子分母足够小时,这样的存储形式支持了以任意精度输出数值值。

当然,你需要支持表示的数字的数量必然与内存开销成正比。

同时,更复杂的结构进行运算时的时间开销,比起浮点数运算的时间开销多出很多很多数量级,对应的机器指令的数量也多出很多很多数量级。
nightwitch
2021-03-19 12:02:04 +08:00
@zealinux sin, cos,tan,sqrt,log,pow 等一大票高频使用的函数都不能用这种记号表示,意义有限
MaxLi77
2021-03-19 12:03:15 +08:00
先问是不是,再问为什么
xingguang
2021-03-19 12:26:55 +08:00
这个好像无解,是编码格式决定的,并不是单纯的二进制转十进制,还有符号位、反码、补码之类的格式限制,不过能到那么多位对决绝大多数场景适用了,如果不适用,那么证明这个公司有能力自己搞一套了
Annoke
2021-03-19 12:30:45 +08:00
想想无限不循环小数?
est
2021-03-19 13:03:31 +08:00
LZ 想法很好,为什么不搞无限精度的浮点,其实可以搞,很多语言的计算库都支持无限精度,但是无限精度就意味着数据格式是变长的,变长的就没法高效率硬件加速计算。CPU 硬件支持的的 FPU 比直接软计算的快的多。
est
2021-03-19 13:10:30 +08:00
可能接下来有人会问,为啥变长的软加速就一定不如定长的硬加速。这个道理就好比,你背熟练了 9x9 乘法口诀表,计算 7x8 当然不用再把 7 个 8 加一遍。定长的硬加速也是类似的原理,直接电路把常见 IEEE754 浮点就能全算出来了。

超出 IEEE754 范围的,变长的,就好比你要计算 46x79 这种乘法了。超出长度了。你没法一口回答出来,不得不一步一步分开计算。效率自然低得多。

现在计算机可能直接告诉你,用 float 就行。没告诉你为啥要用浮点。

因为用 IEEE754 float 效率高啊。计算机当时被发明出来是生产工具的,算弹道,算账。谁效率高谁 nb 。你要追求精度,那就牺牲效率来换呗。
zealinux
2021-03-19 14:53:38 +08:00
@nightwitch 这些都支持
lovecy
2021-03-19 15:06:38 +08:00
我的理解:没有绝对的精确,只有相对精确
float 是相对精确比较高之中效率最高的,所以用 float
laqow
2021-03-19 16:28:10 +08:00
其实有另外一个思路理解这个问题:既然整数是绝对精确的,为什么要用浮点数来计算或储存数值?
很多时候通过设计矩阵或算法能避免计算过程中间出现浮点数,只在输出结果时才输出一个近似值。
jmc891205
2021-03-19 16:32:54 +08:00
巴菲特说过 “宁要模糊的正确,不要精确的错误”( would rather be vaguely right than precisely wrong.)
titan2006
2021-03-20 11:31:26 +08:00
说明编程语言垃圾 数据存储就应该不限制位数

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/762814

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX