4
#include <stdio.h>
int main()
{
    int n;
    while ( scanf( "%d", &n ) != EOF ) {
        double sum = 0,k;
        if( n > 5000000 || n<=0 )   //the judgment of the arrange
            break;
        for ( int i = 1; i <= n; i++ ) {
            k = (double) 1 / i;
            sum += k;
        }
        /*
        for ( int i = n; i > 0; i-- ) {
            k = 1 / (double)i;
            sum += k;
        }
        */
        printf("%.12lf\n", sum);
    }
    return 0;
}

为什么在不同的循环中我得到不同的答案。有浮动错误吗?当我输入5000000sum时,16.002164235299但是当我使用 for (符号部分)的另一个循环时,我得到了 sum 16.002164235300

4

2 回答 2

9

因为浮点数学不是关联的

(a + b) + c不一定等于a + (b + c)

于 2012-11-19T12:33:03.857 回答
1

我还遇到了 a + b + c 问题。完全同意 ArjunShankar。

// Here A != B in general case
float A = ( (a + b) + c) );
float B = ( (a + c) + b) );

在 mantis 中,大多数浮点运算都是在数据丢失的情况下执行的,即使组件很好地适合其中(0.5 或 0.25 之类的数字)。事实上,我很高兴发现我的应用程序中出现错误的原因。我写了简短的提醒文章并详细解释:

http://stepan.dyatkovskiy.com/2018/04/machine-fp-partial-invariance-issue.html

下面是 C 示例。祝你好运!

例子.c

#include <stdio.h>

// Helpers declaration, for implementation scroll down
float getAllOnes(unsigned bits);
unsigned getMantissaBits();

int main() {

  // Determine mantissa size in bits
  unsigned mantissaBits = getMantissaBits();

  // Considering mantissa has only 3 bits, we would then get:
  // a = 0b10   m=1,  e=1
  // b = 0b110  m=11, e=1
  // c = 0b1000 m=1,  e=3
  // a + b = 0b1000, m=100, e=1
  // a + c = 0b1010, truncated to 0b1000, m=100, e=1
  // a + b + c result: 0b1000 + 0b1000 = 0b10000, m=100, e=2
  // a + c + b result: 0b1000 + 0b110 = 0b1110, m=111, e=1

  float a = 2,
        b = getAllOnes(mantissaBits) - 1,
        c = b + 1;

  float ab = a + b;
  float ac = a + c;

  float abc = a + b + c;
  float acb = a + c + b;

  printf("\n"
         "FP partial invariance issue demo:\n"
         "\n"
         "Mantissa size = %i bits\n"
         "\n"
         "a = %.1f\n"
         "b = %.1f\n"
         "c = %.1f\n"
         "(a+b) result: %.1f\n"
         "(a+c) result: %.1f\n"
         "(a + b + c) result: %.1f\n"
         "(a + c + b) result: %.1f\n"
         "---------------------------------\n"
         "diff(a + b + c, a + c + b) = %.1f\n\n",
         mantissaBits,
         a, b, c,
         ab, ac,
         abc, acb,
         abc - acb);

  return 1;
}

// Helpers

float getAllOnes(unsigned bits) {
    return (unsigned)((1 << bits) - 1);
}

unsigned getMantissaBits() {

    unsigned sz = 1;
    unsigned unbeleivableHugeSize = 1024;
    float allOnes = 1;

    for (;sz != unbeleivableHugeSize &&
          allOnes + 1 != allOnes;
          allOnes = getAllOnes(++sz)
          ) {}

    return sz-1;
}
于 2018-04-13T10:40:59.183 回答