c++ - 如何在特定机器上找到尾数长度?

标签 c++ floating-point numerical-methods rounding-error mantissa

我想在特定计算机上查找尾数位数和单位舍入。我了解这些是什么,只是不知道如何找到它们-尽管我知道它们可能因计算机而异。

我需要这个数字来执行数值分析的某些方面,例如分析错误。

我目前的想法是我可以编写一个小型 c++ 程序来缓慢递增一个数字直到发生溢出,但我不确定要使用什么类型的数字。

我在正确的轨道上吗?究竟是如何计算的?

最佳答案

我认为您使用的任何语言都会指定 float 的存储方式。我知道 Java 通过使用特定的 IEEE 标准(我认为是 754)来做到这一点。

如果未指定,我认为您可以通过将 0.5 添加到 1 来进行自己的检查,以查看实际数字是否发生变化。如果是,则将 0.25 添加到 1,将 0.125 添加到 1,依此类推,直到数字不变,例如:

float a = 1;
float b = 0.5;
int bits = 0;
while (a + b != a) {
    bits = bits + 1;
    b = b / 2;
}

如果你只有 3 个尾数位,那么 1 + 1/16 将等于 1。

那么你的尾数位已经用完了。

您实际上可能需要基数为 2 而不是 1,因为 IEEE754 在开头使用隐含的“1+”。

编辑:

看来上述方法可能存在一些问题,因为它为明显具有 4 字节 float 的系统提供 63 位。

这是否与中间结果有关(我对此表示怀疑,因为具有显式强制转换的相同代码 [while (((float)(a + b) != (float)(a))]有类似的问题)或(更有可能,我相信)单位值 a 可以通过调整指数用更接近小数 b 的位来表示,我不还不知道。

目前,最好依靠我上面提到的语言信息,例如 IEEE754 的使用(如果该信息可用)。

我会将有问题的代码留给谨慎的玩家。也许有更多浮点知识的人然后我可以留下一个说明解释为什么它的行为奇怪(请不要猜想:-)。

编辑 2:

这段代码通过确保中间体存储在 float 中来修复它。事实证明 Jonathan Leffler 是对的 - 这是中间结果。

#include <stdio.h>
#include <float.h>

int main(void) {
    float a = 1;
    float b = 0.5;
    float c = a + b;
    int bits = 1;
    while (c != a) {
        bits = bits + 1;
        b = b / 2;
        c = a + b;
    }
    printf("%d\n",FLT_MANT_DIG);
    printf("%d\n",bits);
    return 0;

}

此代码输出 (24,24) 以表明计算的值与头文件中的值匹配。

虽然它是用 C 语言编写的,但它应该适用于任何语言(特别是在标题中不提供信息或在语言文档中指定的情况下)。我只在 C 中进行了测试,因为 Eclipse 需要很长时间才能在我的 Ubuntu 机器上启动:-)。

关于c++ - 如何在特定机器上找到尾数长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/502022/

相关文章:

c++ - 将默认值列表传递给模板类

c++ - BOOST ASIO POST HTTP REQUEST——标题和正文

ruby-on-rails - 将字符串 "2½"(两个半)转换为 2.5

algorithm - 如何计算算法的确切复杂度?

c - 将 regula falsi 方法修改为割线方法

c++ - 为什么 Adapter 会公开继承 Target 而私有(private)继承 Adapter?

c++ - 从未知指针转换为类;如何检查有效性?

java - 将 double 组转换为 float 组

c++ - 带有整数参数的 std::pow,与整数类型进行比较

c++ - 与迭代乘法相比,std::pow() 的数值稳定性如何?