Floating point 为什么在处理大数字和小数字时,浮点比整数和小数更适合物理学家?

Floating point 为什么在处理大数字和小数字时,浮点比整数和小数更适合物理学家?,floating-point,computer-science,Floating Point,Computer Science,我一直在阅读有关浮点的文章,看看它们是什么,一个网站这样说 物理学家需要在同一计算中同时使用大约300000000光速和大约0.0000000000667牛顿引力常数。 为了满足工程师和芯片设计师的要求,数字格式必须提供不同量级数字的精度。然而,只需要相对准确度。为了让物理学家满意,必须能够进行涉及不同量级数字的计算 基本上,拥有固定数量的整数和小数位数是没有用的——解决方案是一种带有浮点的格式 我对第二段有两个问题 对于我处理货币/价格的web应用程序,有人建议我使用decimal作为列类型,

我一直在阅读有关浮点的文章,看看它们是什么,一个网站这样说

物理学家需要在同一计算中同时使用大约300000000光速和大约0.0000000000667牛顿引力常数。 为了满足工程师和芯片设计师的要求,数字格式必须提供不同量级数字的精度。然而,只需要相对准确度。为了让物理学家满意,必须能够进行涉及不同量级数字的计算

基本上,拥有固定数量的整数和小数位数是没有用的——解决方案是一种带有浮点的格式

我对第二段有两个问题

对于我处理货币/价格的web应用程序,有人建议我使用decimal作为列类型,而不是float,因为我处理的是货币,因为某些金额可能会导致错误的答案。 如果浮点不能得到0.1+0.7*10,那么由于舍入误差*,它的计算结果是7,而不是8,那么它如何适用于从非常高到非常低的数字,就像上面引用的关于物理学家的话,考虑到它不能用上一个例子中从0.1到8的数字计算正确答案。 为什么物理学家在计算中使用浮点,为什么不像其他人一样使用精度小数?我被告知不要用它们来赚钱,那么为什么要用它们来做科学呢

此外,如果计算0.1+0.7*10或0.1+0.2等于0.300000000000000004是如此困难,但不是整数,为什么计算机不能只计算没有小数点01+07*10或01+02的和,然后将其放回答案中,再从南部添加小数点1位?我认识一个比我小的17岁的孩子,他正在开发一种可以编译成javascript的编程语言。如果用小的或负数的算术很难计算,为什么程序员不能考虑从和中去掉小数点,然后把小数点放回最终答案中呢?由于他们的重大失误,如果用==或>=相互比较,0.15+0.15和0.1+0.2可能返回为假。这简直是疯了


*7.999999999999999 1118….

财务计算建议使用基数10,因为财务计算受其自身标准的约束,这些标准定义了基数10计算的“正确”结果。使用base-2浮点计算很难模拟正确的计算,因为它与金融标准的base-10语言不匹配

物理学没有基础——遵守物理学的人类标准没有十根手指,所以任何基础都和其他基础一样好。你指出了一个例子,基数2变差了,floor0.1+0.7*10,但同样容易使基数10变差:floor10/3*3=9,当以任何精度以十进制计算时

事实上,涉及楼层的任何计算的问题在于楼层是不稳定的:参数中的小错误可能导致结果中的大错误。如果您避免不稳定的计算,那么对于您的实现来说,一个基础应该和另一个基础一样好。当用逻辑电路实现时,二进制有几个优点

0.15+0.15和0.1+0.2


在0和1之间有无穷多个有理数。其中,您显然希望0.15、0.1和0.2以及它们的总和能够精确表示。如果你有这些期望,那么基数10适合你。物理学家没有任何理由支持这些数字:他们使用π,G,其他我不知道的常数。物理学家习惯于无论如何都不能精确地表示他们的常数,即使其中一个常数恰好是0.1。物理学家并不特别喜欢在0到1之间的所有其他有理数中使用短十进制展开式的数字,其中绝大多数都不会通过一个微不足道的计数参数来精确表示。

在处理数字和日期时!为每项工作使用正确的工具是非常重要的。你至少要考虑一下:

实际结果与计算结果的精度差异 每个进一步计算步骤产生的数值稳定误差裕度 等待计算完成所需的速度/在特定时间范围内可以完成的计算次数 在基本的财务计算中,你处理的是可以计算的事情:在最基本的层面上,你处理的是整枚硬币。这在进行高级计算时是不同的,例如,在处理具有复利的投资或计算具有概率的保险时

当使用分数时,您会遇到一个问题,即使用数字的系统不能用有限的数字来表示大多数分数。 二进制只能表示由1/2、1/4、1/8等组成的分数,例如3/8=1/4+1/8可以表示,而1/10不能表示。十进制稍微好一点。它能比二进制精确地表达更多的分数。但它仍在与1/3这样的简单分数作斗争

如果你想准确地表达分数,你必须把它们表达成分数。这意味着您必须分别计算分子和分母。只有这样你才能得到准确和稳定的结果。但计算将非常缓慢。事实上,像Mathematica和Maple这样的计算机代数系统正是提供了这种模式作为一种选择

当问题领域被很好地理解时,一个人可以通过使用某些捷径获得很多速度。一个捷径是放弃精确性,以近似的结果工作。进行此操作时,以保持所需数值稳定性的方式对部分计算进行排序非常重要。一个非常简单的例子:1/sqrtx不如sqrtx/x精确。进行这种优化需要严格的数学分析。否则,结果不仅不准确,而且完全错误


物理学家可以使用不精确的浮点运算,当她分析对精度的影响时,当她以保持所需数值稳定性的方式对算法进行编码时。在进行高级财务计算时也是如此。事实上,贸易公司雇佣数学家和物理学家来构建交易算法。但是能够进行这种分析的人非常少。因此,对于大多数简单的财务计算,人们被告知只需计算整分钱。

只需投入我的两分钱:

今天的大多数计算机都是以二进制格式进行计算的,因为它很容易在硬件中构建,而且只要使用整数就无关紧要。一个显著的例外是IBMzSeries,可能还有iSeries,它们内置了对二进制编码小数BCD的支持。 将浮点变量用于货币值时的问题不是因为使用浮点表示法,而是因为它们使用的二进制浮点变量不能很好地映射到精确的十进制值。 COBOL和PL/I,特别是zSeries上的COBOL和PL/I,提供了非常适合管理货币数量的十进制定点变量,它们就像您所说的那样:它们记住小数点的位置,所有算术运算都是整数运算的混合,并通过旋转数字来移动小数点的位置。 那个么为什么物理学家要使用像二进制浮点变量这样不精确的东西呢?因为它们处理的大多数值从一开始就不准确。测量得到的每个值都会带来一些误差,因此浮点计算带来的额外模糊性其实并不重要。当0.1实际上是0.1+-10%,0.7是0.7+-5%时,floor0.1+0.7*10没有意义,也可能导致7。
这是一个延伸的评论,而不是一个答案

我想给OP一个简单的挑战,一个机会来证明,如果用小的或负数的算术很难计算,那么从和中删除小数点,然后将小数点放回科学和工程编程的最终答案中的可行性和有效性。当然,这正是像Java的BigDecimal这样的十进制数字系统所做的,软件跟踪小数点的位置

许多科学和工程项目涉及求解线性方程组。更多的涉及类似的线性代数操作。因此,线性方程解是科学计算的常用基准形式

测量一个系统求解1000个线性方程组的速度。它允许对解算器进行更改,因此OP可以编写一个在解算器内部不使用二进制浮点的实现,并获得有效的结果。源代码有多种语言可供使用,提供了一个起点。我建议至少要达到使用IEEE 64位二进制浮点的常规精度。输入以二进制浮点格式提供,但每个二进制浮点数都有精确的十进制表示


许多系统的结果都已公布——参见Jack Dongarra的各种论文,如2013年的论文。在精度和性能方面,将OP的结果与使用二进制浮点的可比硬件的结果进行比较应该不会有什么困难。

浮点运算速度非常快。有些计算需要分发和租用昂贵的硬件。如果我能将计算速度提高10倍,那么我就节省了90%的成本。至于精度误差:10e-15误差相当于抱怨在计算从地球到冥王星的距离时超出了1毫米。是的,我知道它更快,但仔细想想我说的话。如果浮点不能计算
floor0.1+0.7*10正确,只需将两个数字乘以小数点后的1位数,物理学家怎么可能将其用于更小的数字,如0.0000000000667?这毫无意义!和@Bathsheba,地板0.1+0.7*10被计算为8而不是7,这不是10e-15错误或差异。它要大得多。一个写了floor0.1+0.7*10的物理学家将被送回编程课程。你不需要调整任何代码的编写方式。如果您想精确表示以10为基数表示的简单数字,请使用十进制类型的高级语言,并充分利用该类型。每种数字表示格式和算术都是折衷的,因为不可能对一般实数进行表示和精确算术。您可以拾取对给定计算有影响的要素,并基于这些要素选择数字表示。对于许多科学和工程计算来说,二进制浮点是最好的折衷方案,因为基数10没有什么特别之处,重要的输入在计算开始前有测量误差,空间效率和时间效率都很重要。当物理学家计算ππ和其他宇宙常数和数字时,他们是以10为基数,还是以2为基数,或者两者兼而有之?不同的基数之间的数字可互换吗?物理学家是不是所有的计算都用base 2来完成,不仅仅是因为宇宙没有10个手指,而是因为它在超级计算机和租用的云服务器上运行得更快?自从他们从出于技术原因而使用base 10的袖珍计算器转移到计算机之后,物理学家就一直使用base-2进行所有计算。它们写3.14159265358979323846264,计算机知道它们的意思是最接近π的二进制浮点数。实际上,它对1/10的作用是相同的:程序员写0.1,计算机知道程序员的意思是最接近1/10的二进制浮点数。这些规则很简单,也很有效。但是如果你不喜欢这些规则,就像我说的,一些高级语言提供了一种十进制类型,其中包含相同规则的变体。你给出的关于基数10变差的例子是关于除法的,所以显然会有一个余数。你有没有像我说的那样,10进制变差的例子,只包括加法和乘法?@desbest在你的地板上0.1+0.7*10例子,加法和乘法都很好。它是从十进制表示0.1和0.7转换为二进制,这是你认为问题的根本原因。在我的示例中,使用“最接近10/3的十进制近似值”,而不是10/3,这是一个常量,而不是除法。什么你不能表示那个常数吗?您现在开始看到这个问题了。@desbest有些语言内置了常数,表示与pi的精确值最接近的64位二进制浮点。您的答案中的“更多分数”可能会产生误导。当您有64位要分配给分数的表示时,您将得到2^64个精确分数或更少的一位。事实上,IEEE 754的十进制64比IEEE 754的二进制64浪费了更多的位模式。“十进制稍微好一点”这句话原则上只适用于分配了有限数量信息的任何特定格式之外的情况,信息以位进行度量和存储也无济于事。@Pascal Cuoq:我写的不是特定的表示法。二进制可以表示1/2等,而十进制可以编码1/2、1/5和1/10等。@stefan:最大的问题是大多数小数的指数范围很小。它们在这个范围内相当准确,这应该非常适合于金融计算,因为它仍然比地球上所有的钱都要高,不管它的价值是多少,但在外面什么都不可能。IEEE FP可以处理远低于和远高于大多数小数的值。物理学家无论如何也不会使用地板。他会让结果保持原样,非常接近8,但可能略低于8。FWIW,计算整便士并不总是能减少它,因为可能也有1.75%这样的百分比需要计算,但以固定格式计算可能就足够了,否则,比如说,像decimal这样的128位十进制浮点数,NET将涵盖银行家可能需要的一切,还有更多。@RudyVelthuis的IEEE FP在速度方面很好,但在准确性方面不太好。可变长度BCD将更精确,尽管速度要慢得多。128位数字将非常准确,但速度非常慢,尤其是当您想要使用矢量功能时,例如图形卡上的功能。这不会影响大多数银行家,但对于从事算法交易的银行家来说,这可能是一个严重的问题。所以事实上,你总是需要仔细的分析。