#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";
}
3 回答
b0lt已经解释了偏见是如何起作用的 . 猜测一下,也许你想知道为什么他们在这里使用偏差表示,即使几乎所有现代计算机都使用两个's complement, use one' t使用两个's complement, use one' s补码或符号幅度,而不是偏差) .
IEEE浮点标准的目标之一是您可以将浮点数的位视为相同大小的(带符号)整数,如果您按照这种方式对它们进行比较,则值的排序顺序与他们所代表的浮点数 .
如果对指数使用二进制补码表示,则小的正数(即带有负指数)看起来像一个非常大的整数,因为第二个MSB将被设置 . 相反,通过使用偏差表示,您不会遇到这种情况 - 浮点数中的较小指数总是看起来像一个较小的整数 .
FWIW,这也是为什么浮点数通常首先用符号排列,然后用指数排列,最后用最低有效位排列有效数 - 这样,你可以取正浮点数,将这些位作为整数处理,排序他们 . 执行此操作时,结果将以正确的顺序具有浮点数 . 例如:
当我们运行它时,结果如下所示:
正如您所看到的,即使我们将它们排序为整数,这些位表示的浮点数也会以正确的顺序出现 .
这对浮点数有限制 . 虽然所有(非古代)计算机都同意正数的表示,但有三种表示(最近)用于有符号数:有符号量,一个补码和二进制补码 .
只需将这些位视为整数并进行比较,就可以在使用整数的有符号幅度表示的计算机上正常工作 . 对于使用一个's complement or two'补码的计算机,负数将按倒序排序 . 由于这仍然是一个简单的规则,因此编写适用于它的代码非常容易 . 如果我们将上面的
sort
调用更改为以下内容:...然后它会正确地对正数和负数进行排序 . 例如,输入:
会产生以下结果:
在上面的答案中添加更多细节 .
为了在浮点表示
0
,infinity
和NaN
(非数字),IEEE决定使用特殊编码值 .如果指数字段的所有位都设置为0,则浮点数为0.0 .
如果指数字段的所有位都设置为1且小数部分的所有位都为0,则浮点数为无穷大 .
如果指数字段的所有位都设置为1并且小数部分的所有位都不等于0,则浮点数为NaN .
因此,在单精度中,我们有8位来表示指数字段,并且有2个特殊值,所以我们基本上有
256 - 2 = 254
值,可以用exponent表示 . 因此,我们可以在指数中有效地表示-126到127,即254个值(126 127 1),1加0 .在单精度浮点中,您可以获得8位来存储指数 . 不是将它存储为带符号的二进制补码数,而是决定将指数添加127更容易(因为8位签名的最低值为-127)并且只是将其存储为无符号数 . 如果存储的值大于偏差,则表示指数的值为正,如果它低于偏差,则为负,如果等于,则为零 .