我想知道从0D向上第一双由长“相同的值”,由一些增量的偏离时,说1E-8。我虽然没有在这里。我试图做这在C虽然我通常使用管理语言,以防万一。请帮助。


#include <stdio.h>
#include <limits.h>
#define DELTA 1e-8

int main() {
    double d = 0; // checked, the literal is fine
    long i;
    for (i = 0L; i < LONG_MAX; i++) {
         d=i; // gcc does the cast right, i checked
         if (d-i > DELTA || d-i < -DELTA) {
              printf("%f", d);
              break;
         }
    }
}

我猜测的问题是,迪蒙上我的两倍,因此d ==我再差始终为0怎么我还能检测到这种正确 - 我宁愿乐趣ç蒙上比较字符串,这将永远。

ANSWER :正是如我们预期。 2 ^ 53 + 1 = 9007199254740993是根据标准C / UNIX / POSIX工具的差的第一点。由于太多的PAX他的计划。我猜数学再次获胜。

有帮助吗?

解决方案

双打中IEE754具有52位的精度,这意味着它们能准确地存储号码到(至少)2 51

如果您的多头是32位,它们将只具有(正)范围为0〜2 31 所以没有32位长,不能精确地为双表示。对于一个64位长,这将是(大约)2 52 所以我会开始围绕那里,而不是在零。

可以使用下面的程序来检测其中的故障开始发生。一个早期版本我一直依靠,在一些连续加倍最后一个数字如下序列{2,4,8,6}的事实。然而,我最终选择使用已知的受信任的工具(bc)检查的整数,而不仅仅是最后一位。

请记住,这的可以的由sprintf()的行动,而不是双打的实际精度(我不这么认为,因为亲自它与某些数字没有烦恼高达2受到影响< SUP> 143 )。

这是该程序:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *fin;
    double d = 1.0; // 2^n-1 to avoid exact powers of 2.
    int i = 1;
    char ds[1000];
    char tst[1000];

    // Loop forever, rely on break to finish.
    while (1) {
        // Get C version of the double.
        sprintf (ds, "%.0f", d);

        // Get bc version of the double.
        sprintf (tst, "echo '2^%d - 1' | bc >tmpfile", i);
        system(tst);
        fin = fopen ("tmpfile", "r");
        fgets (tst, sizeof (tst), fin);
        fclose (fin);
        tst[strlen (tst) - 1] = '\0';

        // Check them.
        if (strcmp (ds, tst) != 0) {
            printf( "2^%d - 1 <-- bc failure\n", i);
            printf( "   got       [%s]\n", ds);
            printf( "   expected  [%s]\n", tst);
            break;
        }

        // Output for status then move to next.
        printf( "2^%d - 1 = %s\n", i, ds);
        d = (d + 1) * 2 - 1;  // Again, 2^n - 1.
        i++;
    }
}

此保持下去,直到:

2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
   got       [18014398509481984]
   expected  [18014398509481983]

这大约是在我预期它会失败。

顺便说一句,我最初使用的形式的数字2 名词但让我到:

2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 <-- bc failure
   got       [11150372599265311570767859136324180752990210]
   expected  [11150372599265311570767859136324180752990208]

用的双为8个字节大小(与sizeof选中)。原来,这些数字都可以表示与双打长得二进制形式"1000..."的。这时候我切换到使用2 名词 -1,以获得更好的位模式:全1

其他提示

转换为双时不会被1E-8是关闭的第一长为“错误”,它将被1被关闭只要双可以容纳在其有效数长,它将准确地表示它

我忘记了双到底有多少位对精度VS偏移,但会告诉你最大大小都可以表现。第一长是错应该有二进制形式10000 ......,这样你就可以找到它通过从1开始左移快得多。

维基说在有效数位52,不计算隐式的起始1.这应该意味着第一长要被转换为不同的值被2 ^ 53

虽然我不愿提及的Fortran 95和接班人,在这次讨论中,我会提到,Fortran语言自从1990标准提供了一个SPACING固有功能,它告诉你的可表示的REAL之间相差约一个给定的实什么。你可以做这个二进制搜索,间距(X)> DELTA时停止。对于使用相同的浮点模型作为一个你感兴趣的(可能是IEEE754标准),你应该得到相同的结果。编译器

副手,我觉得双打可以代表所有整数(其范围内)完全一样。

如果不是的话,那么你会希望i和d与比二者更精确投的东西。也许很长的双将工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top