这个“非正常数据”是关于什么的?

我想对“非常规数据”有一个广泛的看法,因为我认为我唯一正确的事情是从程序员的角度来看与浮点值特别相关的事实,从CPU的角度来看是计算方法。

有人可以为我解密这两个词吗?

谢谢。

编辑

请记住,我面向C ++应用程序,只有C ++语言。


您询问C ++,但浮点值和编码的具体细节由浮点规范确定,特别是IEEE 754,而不是C ++。 IEEE 754是迄今为止使用最广泛的浮点规范,我将回答使用它。

在IEEE 754中,二进制浮点值用三部分编码:符号位s(0表示正数,1表示负数),偏置指数e(表示指数加固定偏移量)和有效字段f小数部分)。 对于正常数字,它们恰好代表数字(-1)s•2e-bias•1.f,其中1.f是通过在“1.”之后写入有效位而形成的二进制数字。 (例如,如果有效位域具有十位0010111011,则它表示有效位数1.00101110112,它是1.182617175或1211/1024。)

偏差取决于浮点格式。 对于64位IEEE 754二进制,指数字段有11位,偏差为1023.当实际指数为0时,编码指数字段为1023.实际指数为-2,-1,0,1和2已经编码了1021,1022,1023,1024和1025的指数。当有人提到次正常数的指数为零时,它们表示编码指数为零。 实际指数将小于-1022。 对于64位,正常的指数间隔是-1022到1023(编码值1到2046)。 当指数超出此间隔时,会发生特殊情况。

在此间隔以上,浮点数停止表示有限数字。 2047(全1位)的编码指数表示无穷大(有效位域设置为零)。 在此范围之下,浮点数将变为低于正常数值。 当编码指数为零时,有效位字段代表0.f而不是1.f.

这有一个重要的原因。 如果最低指数值只是另一种正常编码,则其有效位的较低位将太小而不能表示为浮点值。 没有那个领先的“1”,就没有办法说出前1位的位置。 例如,假设您有两个数字,均指数最低,并且有有效数字1.00101110112和1.00000000002。 当你减去有效数时,结果是0.00101110112。 不幸的是,没有办法将其表示为正常的数字。 因为您已经处于最低指数,所以您无法表示说明结果中第一个1的位置所需的较低指数。 由于数学结果太小而无法表示,因此计算机将被迫返回最接近的可表示数字,该数字将为零。

这会在浮点系统中创建不需要的属性,您可以拥有a != bab == 0 。 为了避免这种情况,使用了低于正常的数字。 通过使用低于正常的数字,我们有一个特殊的区间,实际的指数不会减少,我们可以执行算术而不会创建太小的数字来表示。 当编码指数为零时,实际指数与编码指数为1时的指数相同,但有效位的值变为0.f而不是1.f. 当我们这样做时, a != b保证ab的计算值不为零。

以下是64位IEEE 754二进制浮点编码中值的组合:

Sign   Exponent (e)   Significand Bits (f)        Meaning
0      0              0                           +zero
0      0              Non-zero                    +2-1022•0.f (subnormal)
0      1 to 2046      Anything                    +2e-1023•1.f (normal)
0      2047           0                           +infinity
0      2047           Non-zero but high bit off   +, signaling NaN
0      2047           High bit on                 +, quiet NaN
1      0              0                           -zero
1      0              Non-zero                    -2-1022•0.f (subnormal)
1      1 to 2046      Anything                    -2e-1023•1.f (normal)
1      2047           0                           -infinity
1      2047           Non-zero but high bit off   -, signaling NaN
1      2047           High bit on                 -, quiet NaN

一些说明:

+0和-0在数学上相等,但是符号被保留。 仔细编写的应用程序可以在某些特殊情况下使用它。

NaN的意思是“不是数字”。 通常,这意味着发生了一些非数学结果或其他错误,应该丢弃或重做另一种计算。 通常,用NaN进行的操作会产生另一个NaN,从而保留出现问题的信息。 例如, 3 + NaN产生NaN。 一个信令NaN意图引起一个异常,或者表明程序出错或者允许其他软件(例如调试器)执行一些特殊的动作。 安静的NaN旨在传播到更多的结果,在NaN只是大量数据集中的一部分并且将在稍后单独处理或将被丢弃的情况下,允许完成大型计算的其余部分。

符号+和 - 与NaN一起保留,但没有数学价值。

在正常的编程中,除了它告诉你浮点运算的限制和行为外,你不应该关心浮点编码。 你不需要对低于正常数字做任何特殊的事情。

不幸的是,一些处理器被破坏,它们违反了IEEE 754标准,通过将低于正常值的数字改为零或者当使用低于正常数字时它们执行得非常慢。 在为这种处理器编程时,您可能会设法避免使用低于正常数量的数字。


要理解非常规浮点值,您首先必须了解正常值。 一个浮点值有一个尾数和一个指数。 在一个十进制值中,如1.2345E6,1.2345是尾数,6是指数。 关于浮点符号的一个好处是,您可以始终将其写入规范化。 类似0.012345E8和0.12345E7与1.2345E6的值相同。 换句话说,只要该值不为零,您可以始终将尾数的第一个数字设置为非零数字。

计算机以二进制形式存储浮点值,数字为0或1.因此,二进制浮点值不为零的属性是始终可以从1开始写入。

这是一个非常有吸引力的优化目标。 由于该值总是从1开始,所以没有必要存储该值。1.它的优点在于,实际上可以免费获得额外的精度。 在64位双精度上,尾数有52位存储。 实际精度为53位,这要归功于隐含的1。

我们必须讨论可以用这种方式存储的最小可能的浮点值。 先用十进制表示,如果你有一个十进制处理器,尾数为5位数,指数为2,那么它可以存储的非零值最小值为1.00000E-99。 1表示不存储的隐含数字(不能用十进制表示,但可以与我一起工作)。 所以尾数店铺00000和指数店-99。 你不能存储一个较小的数字,指数在-99处最大。

那么,你可以。 你可以放弃规范化的表示并忘记隐含的数字优化。 您可以将其存储为非归一化。 现在您可以存储0.1000E-99或1.000E-100。 一直下降到0.0001E-99或1E-103,这是现在可以存储的绝对最小数量。

这通常是可取的,它扩展了可以存储的值的范围。 这在实际计算中往往很重要,非常小的数字在现实世界的问题中很常见,例如差分分析。

然而,它也有一个很大的问题,你失去了正常化数字的准确性。 浮点计算的准确性受限于您可以存储的位数。 我用这个假十进制处理器作为例子很直观,它只能用5位有效数字进行计算。 只要该值被标准化,您总是可以获得5位有效数字。

但是当你解除规范时你会丢失数字。 介于0.1000E-99和0.9999E-99之间的任何值只有4位有效数字。 在0.0100E-99和0.0999E-99之间的任何值只有3位有效数字。 一路下降到0.0001E-99和0.0009E-99,只剩下一位有效数字。

这会大大降低最终计算结果的准确性。 更糟糕的是,它以非常难以预测的方式这样做,因为这些非常小的非标准化值趋于以更多涉及的计算显示。 这当然值得担心,当它只剩下1个有效数字时,你不能真正相信最终的结果。

浮点处理器有办法让你知道这个问题或者解决问题。 例如,当数值变为非归一化时,它们可以生成中断或信号,让您中断计算。 他们有一个“清零”选项,在状态字中有一点告诉处理器自动将所有非正常值转换为零。 这往往会导致无穷大,结果告诉你结果是垃圾,应该丢弃。


来自IEEE文档

如果指数全部为0,但分数非零(否则它将被解释为零),则该值是一个非规格化的数字,它在二进制点之前没有假定的前导1。 因此,这表示一个数(-1)s×0.f×2-126,其中s是符号位,f是分数。 对于双精度,非规格化数字的形式为(-1)s×0.f×2-1022。 由此可以将零解释为一种特殊类型的非规格化数字。

链接地址: http://www.djcxy.com/p/85519.html

上一篇: What is this "denormal data" about ?

下一篇: How are denormalized floats handled in C#?