Что сначала удваивает, который отклоняется от его соответствия долго дельтой?

Вы можете попробовать использовать «перевернутый» компонент Bottom Sheet и заполнить его пользовательским ListView в качестве меню. Я нашел этот репозиторий на github для создания «верхнего листа», надеюсь, это поможет!

5
задан Overflown 9 April 2009 в 06:39
поделиться

4 ответа

Двойные значения в IEE754 имеют точность 52 бита, что означает, что они могут хранить числа с точностью до (как минимум) 2 51 .

Если ваши длинные 32-битные, они будут иметь только (положительный) диапазон от 0 до 2 31 , поэтому нет 32-битных длинных, которые не могут быть представлены точно как двойной. Для 64-битной длины это будет (примерно) 2 52 , поэтому я бы начал там, а не с нуля.

Вы можете использовать следующую программу, чтобы определить, где начинаются сбои. происходят. В более ранней версии я опирался на тот факт, что последняя цифра в числе, которое непрерывно удваивается, следует за последовательностью {2,4,8,6}. Однако в конце концов я решил использовать известный доверенный инструмент (bc) для проверки всего числа, а не только последней цифры.

Имейте в виду, что на этот может повлиять действие sprintf () , а не реальная точность двойных чисел (лично я не думаю, что у него не было проблем) с определенными числами до 2 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 n , но это дало мне возможность:

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]

с размером double, равным 8 байтам (проверено с помощью sizeof ). Оказалось, что эти числа имели двоичную форму «1000 ...» , которая может быть представлена ​​гораздо дольше двойными числами. Именно тогда я переключился на использование 2 n -1, чтобы получить лучший битовый шаблон: все один бит.

Я так не думаю, так как у него не было проблем с определенными числами до 2 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 n , но это дало мне возможность:

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]

с размером double, равным 8 байтам (проверено с помощью SizeOf ). Оказалось, что эти числа имели двоичную форму «1000 ...» , которая может быть представлена ​​гораздо дольше двойными числами. Именно тогда я переключился на использование 2 n -1, чтобы получить лучший битовый шаблон: все один бит.

Я так не думаю, так как у него не было проблем с определенными числами до 2 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 n , но это дало мне возможность:

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]

с размером double, равным 8 байтам (проверено с помощью SizeOf ). Оказалось, что эти числа имели двоичную форму «1000 ...» , которая может быть представлена ​​гораздо дольше двойными числами. Именно тогда я переключился на использование 2 n -1, чтобы получить лучший битовый шаблон: все один бит.

Первоначально я использовал числа вида 2 n , но это дало мне до:

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]

с размером double, равным 8 байтам (проверено с помощью sizeof ). Оказалось, что эти числа имели двоичную форму «1000 ...» , которая может быть представлена ​​гораздо дольше двойными числами. Именно тогда я переключился на использование 2 n -1, чтобы получить лучший битовый шаблон: все один бит.

Первоначально я использовал числа вида 2 n , но это дало мне до:

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]

с размером double, равным 8 байтам (проверено с помощью sizeof ). Оказалось, что эти числа имели двоичную форму «1000 ...» , которая может быть представлена ​​гораздо дольше двойными числами. Именно тогда я переключился на использование 2 n -1, чтобы получить лучший битовый шаблон: все один бит.

12
ответ дан 18 December 2019 в 12:02
поделиться

Первый лонг, который будет «неправильным» при броске на дубль, не будет выключен 1e-8, он будет быть на 1. До тех пор, пока двойник может соответствовать длинному в его значении, он будет точно его представлять.

Я точно забываю, сколько битов имеет двойник для точности по сравнению со смещением, но это скажет вам максимальный размер может представлять. Первое длинное неправильное значение должно иметь двоичную форму 10000 ..., так что вы можете найти его намного быстрее, начиная с 1 и сдвигая влево.

Википедия говорит 52 бита в значении и не считая неявного начала 1. Это должно означать, что первое длинное значение, которое будет приведено к другому значению, равно 2 ^ 53.

2
ответ дан 18 December 2019 в 12:02
поделиться

Я подумал, что двойные числа могут точно представлять все целые числа (в пределах их границ).

Если это не так, то вы захотите привести и i, и d к чему-то с большей точностью, чем любой из них. Возможно, длинный двойной сработает.

0
ответ дан 18 December 2019 в 12:02
поделиться

Хотя я не решаюсь упоминать Fortran 95 и его последователей в этом обсуждении, я упомяну, что Fortran, начиная со стандарта 1990 года, предлагал внутреннюю функцию SPACING, которая сообщает вам, в чем разница между представимыми REAL о данном РЕАЛЬНОМ. Вы можете выполнить двоичный поиск по этому вопросу, остановившись, когда ПРОБЕЛ (X)> ДЕЛЬТА. Для компиляторов, которые используют ту же модель с плавающей запятой, что и интересующая вас (вероятно, это стандарт IEEE754), вы должны получить те же результаты.

1
ответ дан 18 December 2019 в 12:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: