在学习如何在计算机中表示浮点数时,我遇到了“偏差值”这个词,我不太明白。什么是浮点数的“偏差值”?
浮点数的偏差值与浮点数的指数部分的负值和正值有关。
浮点数的偏移值是127,这意味着总是将127添加到浮点数的指数部分。这样做如何帮助确定指数是否为负值或正值?
在学习如何在计算机中表示浮点数时,我遇到了“偏差值”这个词,我不太明白。什么是浮点数的“偏差值”?
浮点数的偏差值与浮点数的指数部分的负值和正值有关。
浮点数的偏移值是127,这意味着总是将127添加到浮点数的指数部分。这样做如何帮助确定指数是否为负值或正值?
在单精度浮点上,您可以获得8位来存储指数。不是将它作为一个带符号的二进制补码存储起来,而是决定只需在指数中加127即可(因为最低的可能是8位有符号的是-127),并将其存储为无符号数。如果存储值大于偏差,则表示指数的值为正数,如果它低于偏差,则为负数,如果相等,则为零。
所以在IEEE格式,由于127点的偏差,如果指数字段是'00000000',那么这意味着数的指数是-127? – 2017-03-21 19:24:37
@KennethWorden没有,全零的指数值是特殊和数字解释为“非规范化”(这包括0本身)。 – 2017-10-27 17:22:44
b0lt已经解释了偏差是如何工作的。有人猜测,也许你想知道为什么他们在这里使用偏差表示,即使几乎所有的现代计算机都基本上在其他地方使用二进制补码(甚至不使用二进制补码的机器,使用补码或符号 - 大小,而不是偏见)。
IEEE浮点标准的目标之一是,您可以将浮点数的位作为具有相同大小的(带符号)整数进行处理,如果您将它们进行比较,则这些值将排序为与它们表示的浮点数的顺序相同。
如果对指数使用二进制补码表示,则小的正数(即具有负指数)看起来像是一个非常大的整数,因为第二个MSB将被设置。通过使用偏差表示来代替,您不会遇到这种情况 - 浮点数中较小的指数总是看起来像一个较小的整数。
FWIW,这也是为什么浮点数通常先按符号排列,然后是指数,最后是最低有效位中的有效位数 - 这样,您可以采用正浮点数,将这些位作为整数,并对它们进行分类。当你这样做的时候,结果将会有正确顺序的浮点数。例如:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
// some arbitrary floating point values
std::vector<double> vals = { 1e21, 1, 2.2, 2, 123, 1.1, 0.0001, 3, 17 };
std::vector<long long> ivals;
// Take those floating point values, and treat the bits as integers:
for (auto &&v : vals)
ivals.push_back(*reinterpret_cast<long long *>(&v));
// Sort them as integers:
std::sort(ivals.begin(), ivals.end());
// Print out both the integers and the floating point value those bits represent:
for (auto &&i : ivals)
std::cout << i << "\t(" << *reinterpret_cast<double *>(&i) << ")\n";
}
当我们运行这个,结果是这样的:
4547007122018943789 (0.0001)
4607182418800017408 (1)
4607632778762754458 (1.1)
4611686018427387904 (2)
4612136378390124954 (2.2)
4613937818241073152 (3)
4625478292286210048 (17)
4638355772470722560 (123)
4921056587992461136 (1e+21)
正如你所看到的,即使我们整理它们为整数,浮点数,这些位也代表按正确的顺序出来。
这对浮点数有一定的限制。尽管所有(非古代)计算机都同意正数的表示形式,但有三种表示法(最近才用于有符号数字):有符号数,补码和二进制补码。
只要将这些位视为一个整数并进行比较,就可以在使用整数的有符号幅度表示的计算机上正常工作。对于使用补码或补码的计算机,负数将按相反顺序排序。由于这仍然是一个简单的规则,所以编写适用于它的代码很容易。如果我们改变了sort
调用上面是这样的:
std::sort(ivals.begin(), ivals.end(),
[](auto a, auto b) { if (a < 0.0 && b < 0.0) return b < a; return a < b; }
);
...这将然后正确的排序都正数和负数。例如,输入:
std::vector<double> vals = { 1e21, 1, 2.2, 2, 123, 1.1, 0.0001, 3, 17, -0.001, -0.00101, -1e22 };
会产生一个结果:
-4287162073302051438 (-1e+22)
-4661071411077222194 (-0.00101)
-4661117527937406468 (-0.001)
4547007122018943789 (0.0001)
4607182418800017408 (1)
4607632778762754458 (1.1)
4611686018427387904 (2)
4612136378390124954 (2.2)
4613937818241073152 (3)
4625478292286210048 (17)
4638355772470722560 (123)
4921056587992461136 (1e+21)
是的,我也想知道为什么。这回答了。很有意思。谢谢。 – mudge 2010-05-14 16:18:36
@JerryCoffin:1优异的应答(特别是FP数目的组件内的顺序的理由)。 – legends2k 2013-07-02 15:00:02
@JerryCoffin我不明白为什么浮点数可以作为整数对待......我的意思是,相同的位的顺序将保持每个数据类型不同的值。你能详细说明吗? – user1534664 2017-07-07 15:38:18
增加更多的细节上面的答案。
为了表示0
,infinity
和NaN
(Not-a-Number)在浮点数,IEEE决定使用特殊的编码值。
如果指数字段的所有位均设置为0,则浮点数为0.0。
如果指数字段的所有位均设置为1,并且小数部分的所有位均为0,则浮点数为无穷大。
如果指数字段的所有比特被设置为1和小数部分的所有位不等于0,则该浮点数是NaN的。
因此,在单精度我们有8位来表示指数字段和有2个特殊值,所以我们基本上具有能够以指数来表示256 - 2 = 254
值。因此,我们可以有效地代表-126到127的指数,即254个值(126 + 127 + 1),1增加了0.1
有关这个问题的另一个有趣的阅读是这个维基百科的文章:HTTPS:/ /en.wikipedia.org/wiki/IEEE_754-1985 – nbro 2016-03-19 14:11:27