为什么我应该使用整数而不是浮点数?

8

我正在为一堂课做准备(我是老师),并试图预测学生可能会问的任何问题,我遇到了一个无法回答的问题:

如果我们有浮点数,为什么还要使用整数?有什么意义呢?

我知道(或者至少我认为)浮点数占用更多的内存,因为它们具有更高的精度,但对于大多数非嵌入式应用程序而言,就内存使用而言,差别几乎可以忽略不计。

我意识到在许多情况下,我们实际上并不需要使用浮点数,但是,老实说,为什么我们首先要使用整数?有什么意义吗?没有任何一种整数可以做到浮点数做不到的。

那么它们为什么存在?

编辑:您可以争论它们更容易书写(3 vs. 3.0),但您可以将所有数字默认为浮点数,因此3将与3.0相同。 为什么要使它成为不同的类型?


2
“一个整数能做的事情,浮点数都能做到。”那么位移或掩码呢? - starrify
1
唔,我不知道,浮点数不能做到那个吗? - temporary_user_name
如果你所说的“float”是指代表其值的原始位,那么它只是一个位字符串,你可以对它做任何事情(比如在浮点数上运行通用图灵机?)。但是,如果你指的是IEEE754及其扩展规范,显然不是这样。 - starrify
3
对于那些对浮点数的性质非常了解的人来说,这是显而易见的,但对于其他人来说则完全不明显。 - temporary_user_name
1
@Aerovistae:并非每个位模式都是有效的浮点值,因此它们不适用于一般的位运算,因为您想要的结果可能在有效值集之外。当然,一种语言可以提供一个浮点类型和一个不包括整数算术的无关类型,用于位操作。 - Steve Jessop
显示剩余4条评论
5个回答

13

浮点数在很多情况下都是近似值。有些整数(和小数)可以被float精确表示,但大多数不能。详情请参见浮点运算:问题与局限性

>>> a = 1000000000000000000000000000
>>> a+1 == a
False
>>> a = 1000000000000000000000000000.0
>>> a+1 == a
True

由于浮点数的近似性质,一些计算可能会产生意外的结果(这与问题并不直接相关,但很好地说明了这一点)。
>>> sum(1.1 for _ in range(9))
9.899999999999999

例如,在处理货币计算时,最好使用整数或(如果速度不是问题)decimal模块

10
你的第一个论点归结为“数学值1.1不能表示为浮点数”。考虑到1.1不能表示为整数,我不明白这是“int可以做而float无法做到”的例子。 - Pascal Cuoq
@PascalCuoq:但是你可以将1.1表示为整数分数“11/10”,并对其进行精确计算。 - Tim Pietzcker
3
我理解这个问题是“为什么不在浮点对象中存储整数?”,但是1.1不是整数。 - David Heffernan
@DavidHeffernan:说得好;我重新排列了段落,以更好地适应问题。 - Tim Pietzcker
1
当你处理货币计算时,最好使用整数。这是一种烦人的谣言。在许多“货币计算”中double是足够好的,并且额外的硬件支持使它们比等效的定点计算在现代机器上要快得多。缺点是如果你想让代码工作,通常必须在编写浮点代码时保持清醒。 - tmyklebu
显示剩余2条评论

9

使用最适合任务的数据类型非常重要。一个数据类型可能以不同的方式适用。例如,单个字节对于人口统计来说是一个不好的选择,因为你无法计算超过255个人。另一方面,浮点数也不是最佳选择,因为许多可能的浮点数值没有意义。例如,1.5作为计数的浮点数值没有意义。因此,使用适当大小的整数类型可以得到最佳匹配。无需执行健全性检查以排除无意义的值。

另一个偏爱整数而不是浮点数的原因是性能和效率。整数运算更快。对于给定的范围,整数消耗更少的内存,因为整数不需要表示非整数值。

另一个原因是显示意图。当代码读者看到您使用了整数时,该读者可以推断出该数量仅意味着取整数值。


1
整数算术的速度快慢取决于您的处理器和使用情况。 浮点数运算现在确实非常快。 - tmyklebu
@tmyklebu 我从未遇到过一台机器,其中fp比int算术更快。 - David Heffernan
1
据我所知,在原始奔腾处理器上,浮点数乘法和除法比整数乘法和除法要快得多。(顺带一提:在现代计算机上,如果另一种选择涉及使用定点数学,则通常最好改用浮点数。但我相信你已经知道这一点了。) - tmyklebu

9

有很多历史原因适用于大多数语言:

  • “不用不必要的东西”的哲学。很多程序不需要非整数值,但却经常使用整数值,所以整数类型反映了问题域。

  • 浮点运算比整数运算昂贵得多。它仍然稍微昂贵一些,但在很多情况下,在Python中你几乎察觉不到差别。

  • 32位IEEE浮点数只能表示所有小于2**24的整数,然后失去精度。16位浮点数(“半精度”)只表示所有整数到2048。因此,在16位和32位计算中,当寄存器大小在性能和值范围之间产生严重权衡时,全都使用浮点数会使这种权衡更加严重。

  • 一个8位整数类型(或平台上存在的任何字节大小),对于低级编程非常有用,因为它恰好映射到内存中可表示的任何数据。对于寄存器大小的整数类型也是如此,在单词而不是字节中工作具有某些效率优势。这些是C语言中的(带符号和无符号)charint类型。

Python还有一个特殊的原因:

  • int类型在计算超出其范围时自动转换为long,从而保留精度。float不会变得更大以保持精度。这两种行为在不同情况下都很有用。

请注意,Javascript没有提供整数类型。Javascript中唯一内置的数字是64位浮点数。因此,对于任何整数类型有益的原因,考虑Javascript如何在没有它的情况下运行是很有启示性的。


2
我目前可以想到四个原因(当然还有更多):
  1. 内存。明智地选择数据类型可以极大地影响内存需求(例如大型数据库)。
  2. 速度。整数算术的硬件实现比浮点算术快得多(而且更简单)。
  3. 编程实践。拥有数据类型强制执行更好的编程实践,程序员必须了解每个变量存储的数据类型。这也允许早期错误检测(编译时与运行时)。
  4. 历史。内存曾经很昂贵(对于某些系统和某些应用程序仍然如此)。

1
第一个观点显然是正确的,但它误导地暗示了整数比浮点数小(大小取决于确切的整数和浮点类型,在Python内置类型中取决于语言版本和解释器“位数”;在Python 3中,甚至取决于整数的值)。第二个观点在今天的台式机上并不正确,即使它是正确的,任何差异也会被Python的普遍缓慢所吞噬(除非是PyPy)。 - user395760

0
我正在学习Python,我也认为只使用浮点数似乎更简单,而不是同时使用浮点数和整数,并试图记住我们将其保存为哪个。有人说“不要使用你不需要的东西。”但是我的大脑存储有限怎么办?这不是我们首先使用计算机代码的原因吗?我不知道。

你的回答目前写得不够清楚。请编辑以添加更多细节,帮助其他人理解这如何回答所提出的问题。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接