【问题标题】:C program not adding float correctlyC程序未正确添加浮点数
【发布时间】:2016-11-17 15:12:14
【问题描述】:

我有一个看起来像这样的方法:

float * mutate(float* organism){   
    int i;
    float sign = 1;
    static float newOrg[INPUTS] = {0};

    for (i = 0;i<INPUTS;i++){
        if (rand() % 2 == 0) {
            sign = 1;
        } else {
            sign = -1;
        }
        float temp = (organism[i] + sign);
        printf("bf: %f af: %f diff: %f sign: %f sign2: %f temp: %f\n\n",
            organism[i], (organism[i] + sign), (organism[i] + sign)-organism[i],
            sign, sign+sign, temp);
        newOrg[i] = organism[i] + sign;
    }

    return newOrg;
}

sign 不为 0 时,前两个 "%f"s 相同,第三个为 0,同样将总和放入变量中也无济于事。这让我很困惑!如果需要,我可以发布完整的代码。

输出:

bf: 117810016.000000 af: 117810016.000000 diff: 0.000000 sign: 1.000000 sign2: 2.000000 temp: 117810016.000000

【问题讨论】:

  • organism[] 的值是多少?这将有助于看到一行输出。也许您没有精确度来加/减 1。
  • sign 不为零时?但是sign从不为零...
  • 如果输入的值非常大,加或减1不会有任何区别,(organism[i] + sign)-organism[i]将等于organism[i] - organism[i]
  • 你为什么使用花车?看来这段代码执行整数运算
  • 此方法将进行相当多的调整,以便以更高级的方式进行变异。添加了示例输出。我刚刚注意到它有时确实有效,但并非总是如此。

标签: c floating-point addition


【解决方案1】:

float 的有限精度。

一个典型的float 只能代表大约 232 个不同的数字。 117,810,016.0 和 1.0 是其中的两个。 117,810,017.0 不是。所以117810016.0 + 1.0 的 C 总和导致117810016.0 的“最佳”答案。

使用像 double 这样的精度更高的类型通常会扩展 +1 精确数学的范围,但即使这样也不会精确到足够大的值(通常约为 9.0*10e15 或 2 53)。

如果要使用float 保留代码,建议将organism[i] 限制为包含范围或±8,388,608.0 (223) 的值。

也许可以对这个任务简单地使用整数类型,比如long long

【讨论】:

  • 我认为如果关注尾数/有效位的位数而不是整个浮点数,答案会更清楚。
  • @njuffa 我发现如果有人有这样的帖子,尾数/有效位的细节不会增加清晰度,并且更喜欢不深入研究float 机制的答案。所以我在这里使用pigeon hole principle。也许有人会根据尾数/有效位数中的位数发布另一个答案供 OP 选择。
  • 目前,答案间接通过为float 提供±8,388,608.0 的范围来引用尾数位数,但没有解释该限制的来源。理解一般原则可能会对未来的读者有所帮助。
猜你喜欢
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多