Bootstrap

漫谈:浮点数为什么很麻烦 金额究竟应该如何存储

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        浮点数和金额是我们尽量回避的东西,因为处理起来很麻烦,坑太多,出了差错责任太大。

要点:

  • 浮点数无法被精确存储
  • 对浮点数做==就是犯罪
  • 处理金融数据的高级方法是使用Decimal类型(C语言不支持)
  • 处理金融数据的巧妙方法是放大到最小精度(从而使用整数)

目录

浮点数的不精确不是因为精度,而是因为二进制表达方式

一种进制下简单的数,在另一种数制下可能是无限的

浮点数绝对不可以==

浮点数运算顺序严重影响结果

金融计算怎么做

关于浮点数格式


浮点数的不精确不是因为精度,而是因为二进制表达方式

        浮点数是个很麻烦的东西,浮点数是不精确的。

        不精确的原因不是因为精度不足,而是因为十进制和二进制在小数部分的转换可能是无法精确对应的。

        二进制的整数部分,跟十进制相比,不过是长了一些。

        二进制的小数部分,第一位是0.5,第二位是0.25,第三位是0.125,依此类推。那么十进制0.1的二进制什么样?

        第一位不够,0

        第二位不够,0

        第三位还是不够,0

        第四位是0.0625,够,1,剩余0.0375

        第五位是0.03175,够,1,剩余0.00575

        再继续……可以想象,后面遇到一个凑巧可以使剩余为0的不会很容易。

        0.1的二进制是0.0001100110011001100110011001100110011001100110011001101(我不知道后面还有没有)。

一种进制下简单的数,在另一种数制下可能是无限的

        比如十进制三分之一,是个无限循环小数0.3333333......,而对于三进制,就是0.1啊,多简单。(三进制计算机并非没有人尝试过)

        所以说,这不是精度问题,精度再高也不能存储无限多的数字。

浮点数绝对不可以==

        所有C语言教材在讲到浮点数的时候应该都会讲到不可以对浮点数进行==比较,只能用“x-a<0.000001 || a-x<0.000001”之类的方法来比较,差值的绝对值小于某个数就算相等。

浮点数运算顺序严重影响结果

        学习数值计算的时候,第一课就是浮点数的精度问题,不仅仅是不精确,而且,浮点数的运算顺序也严重会影响结果,书上的建议是,避免对数量级差别很大的数字进行运算。当然,数值运算是一个专门的领域,解方程的,逃不开浮点数。

金融计算怎么做

        对于大部分程序员而言,现实中很少用到浮点数。遇到金额问题怎么办?其实与金额有关的计算都有最小单位要求,不到最小单位的按规定舍去或进位,程序都是用整数来存储数据的。

        比如有些系统业务要求就是精确到分,所以所有金额在内部就是直接乘以100,按照分来存储的。

        数据库和高级语言基本都支持Decimal类型,专门用于存储金融类型,其实就是保持了十进制,避免了转换到二进制造成的误差。但是呢,没有CPU支持啊!所以一定会很慢。

关于浮点数格式

        浮点数格式是国际标准,分两种:单精度和双精度。单精度四字节,双精度八字节。

        浮点数格式是抽象的,超越编程语言,和机器是32位还是64位也没有关系。但是具体到设备,存在字节序问题,网络传输的时候要考虑这个问题。


(这里是结束)

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;