什么是从其相应的长三角洲偏离双第一? [英] What's the first double that deviates from its corresponding long by delta?

查看:119
本文介绍了什么是从其相应的长三角洲偏离双第一?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道,从0D向上双第一,通过长期的同值有些三角洲偏离,说1E-8。我虽然没有在这里。我试图做这在C虽然我通常使用托管语言,以防万一。请帮助。

I want to know the first double from 0d upwards that deviates by the long of the "same value" by some delta, say 1e-8. I'm failing here though. I'm trying to do this in C although I usually use managed languages, just in case. Please help.


#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;
         }
    }
}

我猜测的问题是,迪蒙上我将翻一番,因此Ð==我再差始终为0怎么我还能检测到这种正确的 - 我想preFER乐趣Ç铸造在比较字符串,这将永远走。

I'm guessing that the issue is that d-i casts i to double and therefore d==i and then the difference is always 0. How else can I detect this properly -- I'd prefer fun C casting over comparing strings, which would take forever.

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

ANSWER: is exactly as we expected. 2^53+1 = 9007199254740993 is the first point of difference according to standard C/UNIX/POSIX tools. Thanks much to pax for his program. And I guess mathematics wins again.

推荐答案

翻番IEE754有52位的precision这意味着它们可以准确地存储数字高达(至少)2 51

Doubles in IEE754 have a precision of 52 bits which means they can store numbers accurately up to (at least) 251.

如果您的多头是32位的,他们只会有(正)范围0〜2 31 所以没有32位长,不能再presented正是作为双。对于一个64位长,这将是(大约)2 52 所以我会首发身边有,不为零。

If your longs are 32-bit, they will only have the (positive) range 0 to 231 so there is no 32-bit long that cannot be represented exactly as a double. For a 64-bit long, it will be (roughly) 252 so I'd be starting around there, not at zero.

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

You can use the following program to detect where the failures start to occur. An earlier version I had relied on the fact that the last digit in a number that continuously doubles follows the sequence {2,4,8,6}. However, I opted eventually to use a known trusted tool (bc) for checking the whole number, not just the last digit.

请记住,这的可以的通过的sprintf 的行动受到影响(),而不是双打的实际精度(我不知道这样想亲自因为它有一定的数量不会遇到麻烦最多2 143 )。

Keep in mind that this may be affected by the actions of sprintf() rather than the real accuracy of doubles (I don't think so personally since it had no troubles with certain numbers up to 2143).

这是程序:

#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]

这是在哪里我预期要失败的。

which is about where I expected it to fail.

顺便说一句,我最初使用表单数2 N 但让我到:

As an aside, I originally used numbers of the form 2n but that got me up to:

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 ......可重新psented与双打长得$ P $。这时候,我转向使用2 N -1以获得更好的位模式:全1

with the size of a double being 8 bytes (checked with sizeof). It turned out these numbers were of the binary form "1000..." which can be represented for far longer with doubles. That's when I switched to using 2n-1 to get a better bit pattern: all one bits.

这篇关于什么是从其相应的长三角洲偏离双第一?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆