为什么需要浮点/双精度?


29

我正在看http://www.joelonsoftware.com/items/2011/06/27.html并嘲笑乔恩·斯凯特(Jon Skeet)的笑话,说的不是0.3,而是0.3。我个人从来没有浮点数/小数/双精度问题,但是后来我记得我很早就学习了6502,并且在我的大多数程序中都不需要浮点数。我唯一的使用时间是用于图形和数学,其中数字不正确,输出用于屏幕,而不是存储在(db,文件中)或依赖于屏幕。

我的问题是,您通常在哪里使用浮点数/小数/双精度数?所以我知道要提防这些陷阱。有了钱,我使用多头并以美分存储值,为了提高游戏中对象的速度,我添加了整数并除(或移位)了该值,以了解是否需要移动像素。(我在6502天内使对象移动,我们没有划分或浮动,但有移动)。

所以我主要是好奇。


10
因为非常重要,因为我支付给我的抵押贷款的利息仍然是12.6,并且不会变为13,所以cos 13是一个很好的整数。
Chani

1
“我很早就学会了6502,并且在我的大多数程序中都不需要浮点数...为了提高对象的速度,我添加了一个整数并除以该值以知道是否移动像素。” 这些是在现代实践中完成这些任务的非常不寻常的方式,除了以美分表示的钱。
jprete 2011年

电脑了解千篇一律的好东西。
tylermac

1
或者另外,为什么可以使用分数时使用小数?
tylermac

6
@Scrooge-具有讽刺意味的是,您不能在浮动中代表0.6。
马丁·贝克特

Answers:


28

因为在大多数情况下,它们比整数准确。

现在怎么样?“对于游戏中物体的速度...”就是这种情况的一个很好的例子。假设您需要使用一些非常快速的物体,例如子弹。为了能够使用整数速度变量来描述它们的运动,需要确保速度在整数变量的范围内,这意味着您不能拥有任意精细的栅格。

但是,然后,您可能还想描述一些非常慢的对象,例如时钟的时针。因为这比子弹对象慢大约6个数量级,所以第一个ld(10⁶)≈20位为零,short int从一开始就排除了类型。好的,今天我们long到处都是,这仍然给我们留下了舒适的12位。但是即使那样,时钟速度也只能精确到小数点后四位。那不是一个很好的时钟...但是对于游戏来说当然可以。只是,您不希望使栅格变得比现在更粗糙。

...这会导致问题,如果有一天您想引入一种新的甚至更快的对象。没有剩余的“净空”。

如果选择浮点类型会怎样?相同大小的32位,但现在对所有对象都具有完整的24位精度。这意味着时钟具有足够的精度,可以保持长达数秒的时间同步。子弹没有更高的精度,但是无论如何它们只能“存活”几分之一秒,因此,如果有的话,那将毫无用处。你,如果你想描述不进入任何种类的麻烦甚至更快的对象(为什么不光速?没问题)的人或慢得多。当然,在游戏中您不需要这些东西,但有时在物理模拟中则需要。

使用浮点数,您始终可以得到相同的精度,而不必首先巧妙地选择一些非显而易见的栅格。这也许是最重要的一点,因为这种选择的必要性很容易出错。


整数非常准确。错误的原因是由于计算错误而引起的。
fjdumont

15
仅当使用整数来实际表示整数(ℤ)时,整数才是完全准确的。表示其他任何东西的确意味着错误的计算。在这种情况下,您有两种可能:要么定义一种完全适合您实际想要表示的数字的类型。这是可能的,例如Mathematica可以做到。但这非常复杂且耗时,通常不值得付出努力,因为您实际上并不需要完美的精度。但是您确实需要很高的精度,而在那儿,浮点数通常比整数要好。
大约

53

在描述连续值而不是离散值时,可以使用它们。没有比这更复杂的描述了。只是不要误以为任何带小数点的值都是连续的。如果一次全部更改,例如添加一分钱,它就是离散的。


28

您这里确实有两个问题。

为什么有人需要浮点数学呢?

正如卡尔·比勒费尔特(Karl Bielefeldt)所指出的那样,浮点数使您可以对连续的数量进行建模-并且您可以在整个地方找到这些数量-不仅在物理世界中,甚至在诸如商业和金融领域。

我在编程职业的许多领域都使用过浮点数学运算:化学,在AutoCAD上工作,甚至编写了Monte Carlo仿真器进行财务预测。实际上,有一个叫David E. Shaw的家伙,他将基于浮点的科学建模技术应用于华尔街,赚了数十亿美元。

当然,还有计算机图形学。我咨询开发用于用户界面的糖果的方法,而如今在没有扎实的浮点,三角学,微积分和线性代数的理解的情况下,这样做似乎就像在用一把小刀进行枪战。

为什么有人需要浮动还是双重浮动

使用IEEE 754标准表示形式,32位浮点数可为您提供约7个十进制数字的精度,并且指数范围为10 -38到10 38。64位双精度数为您提供大约15个十进制数字的精度,指数范围为10 -307到10 307

浮动似乎足以满足任何人的合理需求,但事实并非如此。例如,许多现实世界中的数量用7个以上的十进制数字表示。

但更巧妙地讲,存在一个通俗地称为“舍入错误”的问题。二进制浮点表示法仅适用于小数部分的分母为2的幂的值,例如1 / 2、1 / 4、3 / 4等。要表示其他小数,例如1/10,请“四舍五入”值最接近的二进制分数,但这有点错误-这就是“舍入误差”。然后,当您对那些不准确的数字进行数学运算时,结果中的不准确性可能会比开始时要严重得多-有时错误百分比会成倍增加,甚至呈指数增长。

无论如何,您必须使用的二进制数字越多,四舍五入的二进制表示形式与您要表示的数字越接近,因此其舍入误差会更小。然后,当您对其进行数学运算时,如果要处理的数字很多,则可以在累积舍入误差累积成问题之前进行更多的操作。

实际上,具有15个十进制数字的64位双精度对于许多应用程序来说还不够好。我在1985年使用80位浮点数,而IEEE现在定义了一个128位(16字节)浮点类型,我可以想象使用这种类型。


2
+1鲍勃我在天文望远镜等高分辨率控制系统上的经验是,除非您对条件进行排序,否则64位双精度不够好。同上,用于火力控制和远程导航
Tim Williscroft

20

这是一个普遍的误解,在您处理货币的任何地方,都应将其值存储为整数(分)。在某些简单情况下(例如在线存储),这是事实,但是,如果您有更高级的功能,它并没有太大帮助。

举个例子:一个开发人员每年赚10万美元。他确切的月薪是多少?使用整数可以得到$ 8333.33(¢833333)的结果,乘以12即为$ 99,999.96。将其保留为整数有帮助吗?不,不是。

银行是否总是使用十进制/整数值?好吧,他们做交易的一部分。但是,例如,一旦您开始谈论投资银行业务,除了跟踪实际交易,其他所有内容都是浮动的。由于它们都是内部代码,因此您将看不到它,但是您可以在QuantLib处发现一个峰,该峰本质上是相同的(除了更干净的;-)。

为什么要使用浮点数?因为在使用平方根,对数,具有非整数指数的幂等函数时,使用十进制根本没有帮助。当然,浮点数比十进制类型要快得多。


1
@Job-小数和浮点数非常不同。您可以精确地以十进制类型存储0.1,但不能以浮点数或双精度数存储。
Scott Whitlock

3
我还有一个问题。如果您付款$100,000/12并使用了浮动。为什么结果恰好是100,000美元?为什么每次有人付钱时,浮点数(或小数)都不会向上或向下取整?我说的是写支票(不能做1/2或1/3分)或直接存款(我认为它有相同的限制)时

@acid:>>> X = 100000 / 12.0 >>> X * 12 100000.0
vartec

重读我的评论?我的问题是当我每月使用软件创建支票时。既然不能支付1/2美分,那么一年后该人如何获得全部款项?

2
@acid:您不能使用直接除法,无论您使用整数,小数还是除以浮点数然后取整。这就是重点,使用十进制对这种情况没有帮助。
vartec

4

您所描述的是在控制所有输入和输出的情况下的理想解决方法。

实际上,情况并非如此。您将需要能够以某种真实值在某种程度上为您提供数据的系统,并期望您以相同的格式返回数据。在这种情况下,您遇到这些问题。

实际上,即使您使用列出的技巧,也会遇到这些问题。在计算价格的17.5%税时,无论您将价值存储为美元还是美分,都将得到分数美分。您必须弄清四舍五入的正确性,因为如果您付给他的钱不够多的话,税务员会很不高兴。使用正确的money类型(无论使用何种语言,它们都会使您免于痛苦)。


什么是货币类型?(语言或参考链接),为什么是“正确”类型?是因为它的128位或更多位吗?我的另一个人为什么使用我的“技巧”是不正确的?您有百分之一的整数。如果将其乘以.175,将得到一个整数并将其用于任何您想要的。考虑到您的示例,我认为float能够以足够的精度保存我的值,但是我不必担心0.3f == 0.3d是错误的。-edit-和+1

1
@ acidzombie24-我的意思不是特定类型,而是您的语言用来代表金钱价值的任何类型。另外,如果您有10美分并乘以0.175,则您有1.75美分-如何用整数算术处理呢?是1美分还是2美分?弄错了,您的客户最终可能会拥有很多税款。
克里斯·

您绝不能将10(一个整数)乘以.175(一个实数/浮点数),因为您不应该将精确数字与不精确的数字混合使用;结果将是不精确的。换句话说,在精确数字系统中,像.175这样的值将永远不存在,因此这是一个无意义的计算。更好的解决方案是将10000乘以175,然后在适当的地方手动插入小数点。
巴里·布朗

8
@Barry-我知道。我试图说明您遇到的问题的类型。如果税率为17.5%,并且您需要计算成本为10美分的商品的税,则还会存在类似0.175的值。
克里斯·

1
@acidzombie:用于金钱的正确类型是精度较高(至少4个小数点)的定点小数。没有if,ands或buts。钱存放值毛钱足够的,因为实际上它只是给你的精度两分。
亚罗诺(Aaronaught)2011年

3

“上帝创造了全部数字,其他一切都是人类的工作。” – Leopold Kronecker(1886)。

根据定义,您不需要任何其他类型的数字。一种编程语言的图灵完整性是基于各种数字之间的简单关系。如果可以使用整数(a / k / a自然数),则可以执行任何操作。

这个问题有点似是而非,因为您不需要它们。也许您想要方便,理想,便宜或更便宜的地方?


7
我们也可以省去整数,因为也可以只使用集合理论运算和空集合来构造它们。但是,这和图灵完整性的争论都是将学术还原论带到了一个极端。
Bob Murphy

4
同样,图灵完整性仅适用于计算。整数和有理数在数学上都不是完整的,因为它们都不满足柯西序列的收敛性。因此,克罗内克(Kronecker)充满了热气:如果您想要一个包含整数的完整度量空间,则必须变得真实:xkcd.com/849
Bob Murphy

1
@鲍勃·墨菲:“学术还原主义到了极点”。精确地 这个问题很差,因此可能给出答案。
S.Lott

2

一句话,浮点十进制类型封装了往返于整数值的转换(这是计算机所知道的所有在二进制级别处理的方式;二进制中没有小数点)提供了逻辑上的,通常易于实现的了解用于十进制数字计算的界面。

坦白地说,说您不需要浮点数是因为您知道如何使用整数进行十进制数学运算,就像说您知道如何进行算术运算,那么为什么要使用计算器呢?所以你知道这个概念;太棒了 并不意味着您必须一直练习这些知识。只需说3.5 + 4.6 = 8.1,而不是将信号无花果转换成整数,通常对于非二进制专家来说更快,更便宜并且更容易理解。


1

浮点类型的主要优点是,从运行时的角度来看,两种或三种格式(我希望更多语言支持80位格式)足以满足大多数计算目的的需要。如果编程语言可以轻松支持一系列定点类型,则定点类型所需的硬件复杂度通常比定点类型要低,而浮点类型则要低。不幸的是,提供这样的支持绝非易事。

为了使一种编程语言有效地满足98%的应用程序的数字需求,它必须包含数十种类型,并为可能的数百种组合提供定义操作。此外,即使编程语言具有出色的定点支持,某些应用程序仍将需要在足够大的范围内保持大致恒定的相对精度,从而需要浮点数。鉴于在任何情况下在某些情况下都需要浮点数学运算,让硬件供应商专注于使用两种或三种浮点格式的数学性能,并让代码在合理工作的情况下使用这些格式通常会取得更好的效果比起尝试优化定点数学的行为,“花钱多了”。

顺便说一句,定点数学在8位和16位处理器上比在32位处理器上更有优势。在8位处理器上,在32位不够的情况下,40位类型的空间仅比32位类型多25%的空间和25-50%的时间,并且需要37.5%与64位类型相比,空间更小,时间节省了37.5-60%。在32位平台上,如果32位类型不足以满足某些要求,则通常没有理由使用少于64位的内容。如果48位定点类型足够了,则64位“ double”将与定点类型一样工作。


0

通常,您应该非常小心地使用它们。理解即使是简单的计算也可能导致精度损失是一个挑战。例如,对这样的数字列表取平均值是一个非常糟糕的主意:

double average(List<Double> data) {
  double ans = 0;
  for(Double d : data) {
    ans += d;
  }
  return ans / data.size();
}

原因是,对于足够大的列表,当ans变得足够大时,您基本上会丢失所有数据点(例如,参见this)。此代码的问题在于,对于较小的列表,它可能仅会工作---仅在破坏时才是规模。

就个人而言,我认为您仅应在以下情况下使用它们:a)计算确实必须快速;b)您不在乎结果是否可能遥遥无期(除非您真的知道自己在做什么)。


-1

一种想法是,当您需要处理整数范围之外的值时,将使用浮点或双精度表示形式。

当今的体系结构(大约)的有符号整数范围为+/- 2,147,483,647(32位)或+/- 9,223,372,036,854,775,807(64位)。Unsigned将其扩展了2倍。

IEEE 754浮点数(大约)从+/- 1.4×10 ^ −45变为3.4×10 ^ 38。Double将范围扩大到+/- 5×10-324±2.225×10 ^ -308,此处省略了许多条件和细节。

当然,最令人惊讶的明显原因是您可能需要表示-0 ;-)


数字主要来自维基百科的文章,仅供说明。除了-0之外,这只是为了好玩。
斯蒂芬

问题在于在这个巨大范围内有很多整数根本没有被表示出来。
巴里·布朗

@BarryBrown绝对正确。不过,“省略了很多条件和细节”。
斯蒂芬

-1

通常的原因是因为它们很快,因为JVM通常使用底层硬件支持(除非您使用strictfp)。

请参阅https://stackoverflow.com/questions/517915/when-to-use-strictfp-keyword-in-java,了解strictfp的含义。


浮点数学比整数数学快吗?在什么处理器上,浮点计算比整数计算需要更少的周期?
this.josh 2011年

1
@ this.josh在很大程度上取决于您数字中的位数。同样,整数不能精确除法,这可能很重要,也可能不重要。

-2

这就是为什么我们需要256位操作系统。

木板长度(您可以测量的最小距离)= 10 ^ -35m
可观察的范围为14Bn秒差距= 10 ^ 25m,
因此,如果您只有200位精度,则可以以整数形式测量任何木板长度单位。


2
-1:如果您要模拟的事物比可观察的宇宙大,那该怎么办?
amara

2
@sparkleshy,这就是FAR指针的作用!
马丁·贝克特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.