从整数转换为单精度时可能会失去精度


27

当我进入该部分时,我正在阅读Microsoft的一篇有关扩大转换和严格选择的文章。

以下转换可能会失去精度:

  • 整数到单
  • 长到单或双
  • 小数到单或双

但是,这些转换不会丢失信息或幅度。

..但根据另一篇有关数据类型的文章

  • 整数类型可以存储-2.147.483.648至2.147.483.647和

  • 单一类型可以存储

    • 1,401298E-45到3,4028235E + 38(正数),
    • 和-3,4028235E + 38到-1,401298E-45(对于负数)

..因此Single可以比Integer存储更多的数字。我不明白在什么情况下从Integer转换为Single可能会失去精度。有人可以解释一下吗?

Answers:


87

单数可以存储比整数更多的数字

不,不能。两者SingleInteger都是32位,这意味着两者都可以存储完全相同的数字量,即2 32 = 4294967296个不同的数字。

由于范围Single明显的比大时,它是立即明显(因为的鸽巢原理),它不可能表示该范围内的所有数字。

并且由于的范围与和都可以表示Integer的最大数量的大小完全相同,但是也可以表示超出该范围的数字,因此很显然,它不可能表示范围内的所有数字。IntegerSingleSingleInteger

如果其中有一些Integer不能表示Single,则从转换IntegerSingle 必定会丢失信息。


3
尽管问题实际上是在什么时候(“在什么情况下”)发生,但对于为什么一定要这样的一个很好的解释+1 …
doubleYou

21
@doubleYou:4294967296中Integer的4261412864 (99.2%)无法表示为Single,因此“何时”是“几乎总是”。
约尔格W¯¯米塔格

2
如果要更精确,Single只能代表4,278,190,079个不同的数字。甲Single值代表一个数字当且仅当所存储的指数不为255,这意味着有255个* 2 ^ 24 SingleS的表示数字。其中有两个代表相同的数字(即零),其他都代表不同的数字。
Tanner Swett

10
en.wikipedia.org/wiki/Single-precision_floating-point_format解释了限制为很好IEEE754 binary32。[-16777216,16777216]可以精确表示(2 ^ 24 =有效宽度)中的整数。较大的数字将四舍五入到2、4、8 ...的最接近倍数,具体取决于它们的大小。
Peter Cordes

14
“这意味着既可以存储数字完全相同的量” -它不是那个意思。这仅意味着两种类型都具有完全相同数量的存储每个数字的方式。事实并非如此;例如,Single有两种存储零的方法。因此Single,实际上可以表示比更少的不同数字Integer
Konrad Rudolph

28

浮点类型(例如,Single和Double)在内存中由符号,尾数和指数表示。将其视为科学计数法:

Sign*Mantissa*Base^Exponent

正如您所期望的那样,它们使用基数2。还有其他一些调整可以表示无穷大和NaN,并且指数是偏移的(将返回到该值),并且尾数的一种缩写(也将返回到该值) 。寻找有关其表示和操作的标准IEEE 754,以获取更多详细信息。

出于我们的目的,我们可以将其想象成一个二进制数字“尾数”和一个“指数”,告诉您将小数点放在哪里。


在Single的情况下,他的符号为1位,指数为8位,尾数为23位。

现在,问题是,我们将从最高有效位开始存储尾数。请记住,左边的所有零都不相关。考虑到我们使用二进制工作,我们知道最高有效数字是1※。好吧,由于我们知道这一点,所以我们不必存储它。由于该缩写,尾数的有效范围是24位。

※:除非我们存储的数字为零。为此,我们将所有位设置为零。但是,如果我们尝试按照我给出的描述来解释,您将有一个2 ^ 24(隐式1)乘以1(2为指数0的幂)。因此,要解决此问题,指数零是一个特殊值。还有一些特殊值可存储指数中的无穷大和NaN。

根据指数偏移量(除了避免使用特殊值外),让其偏移量允许将小数点放置在尾数开头之前或尾数结尾之后,而无需为指数指定符号。


这意味着对于大数,浮点类型会将小数点放在尾数末尾之外。

请记住,尾数是24位数字。它永远不会代表25位数字...它没有多余的位。因此,单身人士无法区分2 ^ 24和2 ^ 24 + 1(这是前25位数字,而他们在最后一位上有所不同,这在单身人士中没有体现)。

因此,对于整数,单数的范围是-2 ^ 24到2 ^ 24。尝试将1加到2 ^ 24将导致2 ^ 24(因为就类型而言,2 ^ 24和2 ^ 24 + 1是相同的值)。在线试用。这就是为什么从整数转换为单数时会丢失信息的原因。这也是为什么在不引起您注意的情况下,使用一个或一个双精度循环实际上可能是无限循环的原因。


这不是1有效位数中隐含的前导位的完美解释。偏置指数字段非零暗示了这一点。次常态(又称非常态)包括+-0.00其有效位的前导位。我想您可以简化为只考虑0.0一种完全特殊的情况,但0.0实际上遵循的编码规则与其他次规范相同。
Peter Cordes

25

这是从转换IntegerSingle精度时的实际示例:

Single类型可以存储从-16777216到16777216(含)的所有整数,但不能存储此范围之外的所有整数。例如,它不能存储数字16777217。因此,它不能存储任何大于16777216的奇数。

我们可以使用Windows PowerShell查看将Integera 转换为a Single并返回的情况:

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

请注意,将16777217舍入为16777216,将16777219舍入为16777220。


4
随着幅度的增加,最接近的可表示floats 之间的距离随着幂的增加而不断增长。 en.wikipedia.org/wiki/…–
彼得·科德斯

12

浮点类型类似于物理学中的“科学记数法”。该数字分为符号位,指数(乘数)和尾数(有效数字)。因此,随着值的增加,步长也会增加。

单精度浮点有23个尾数位,但是有一个“隐式1”,因此尾数实际上是24位。因此,所有大小最大为2 24的整数都可以用单精度浮点数精确表示。

超过此数量,可以表示更少的数字。

  • 从2 24到2 25,只能表示偶数。
  • 从2 25到2 26只能表示4的倍数。
  • 从2 26到2 27,只能表示8的倍数。
  • 从2 27到2 28,只能表示16的倍数
  • 从2 28到2 29只能表示32的倍数
  • 从2 29到2 30,只能表示64的倍数
  • 从2 30到2 31只能表示128的倍数

因此,在2 32个可能的32位带符号整数值中,仅2 *(2 24 + 7 * 2 23)= 9 * 2 24可以用单精度浮点表示。占总数的3.515625%。


8

单精度浮点数具有24位精度。超出的任何内容将四舍五入到最接近的24位数字。用十进制科学计数法可能更容易理解,但请记住,实际的浮点数使用二进制。

假设您有5个十进制数字的内存。您可以选择使用常规的unsigned int之类的数字,允许您使用0到99999之间的任何数字。如果您希望能够表示更大的数字,则可以使用科学计数法并仅分配两位数字作为指数,因此您现在可以表示0到9.99 x 10 99之间的任何值。

但是,现在可以精确表示的最大数字只有999。如果尝试表示12345,则可以得到1.23 x 10 4或1.24 x 10 4,但是您不能表示两者之间的任何数字,因为您没有足够的数字。


3
使用十进制数字是个不错的主意,它使它更易于理解,但是最后一段有点误导性:实际上,您可以表示大于999的数字,而您的示例显示出来:12300将为1.23 x 10 <sup> 4 <sup >。您的意思是,从该数字开始存在差距。您介意一下吗?
法比奥说莫妮卡
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.