Заокруглення з плаваючою комою


13

Чи може число IEEE-754 з плаваючою точкою <1 (тобто генерується генератором випадкових чисел, що генерує число> = 0,0 та <1,0), коли-небудь можна помножити на деяке ціле число (у формі з плаваючою комою), щоб отримати число, рівне або більше, ніж це ціле число через округлення?

тобто

double r = random() ; // generates a floating point number in [0, 1)
double n = some_int ;
if (n * r >= n) {
    print 'Rounding Happened' ;
}

Це може бути еквівалентно тому, що існують такі N і R, що якщо R є найбільшим числом, меншим від 1, яке може бути представлено в IEEE-754, то N * R> = N (де * і> = є відповідними IEEE- 754 операторів)

Це випливає з цього питання на основі цієї документації та випадкової функції postgresql


Чи можете ви сказати що-небудь про діапазон N, тобто він достатньо малий, щоб бути точно представленим у подвійній точності IEEE-754?
Педро

@ Педро У цьому конкретному випадку так, це було б невелике ціле число - тобто 10. Я припускаю, що ви говорите, що якщо N дуже велике ціле число з дуже великою кількістю значущих цифр, воно може бути неможливо точно представити?
Кейд Ру

Саме, якщо , то е л ( Р × е л ( Н ) ) може бути більше , ніж R N . fl(N)>Nfl(R×fl(N))RN
Педро

Відповіді:


8

Якщо припустити, що округлює до найближчого і що , то N R < N завжди. (Будьте обережні, щоб не конвертувати занадто велике ціле число.)N>0NR<N

Нехай , де c [ 1 , 2 ) - значення, а q - ціле число. Нехай 1 - 2 - s = R і виводимо пов'язанеc2q=Nc[1,2)q12s=R

NR=c2q(12s)c2q2qs,

з рівністю тоді і тільки тоді, коли . Права частина менша за N і, оскільки 2 - q - s рівно 0,5 одиниць на останньому місці N , або c = 1 і 2 - q - 2 - q - s є точно представним (оскільки N є нормальним і не найменший нормальний), або c > 1 , і найближче округлення вниз. В обох випадках N R менше Nc=1N2qs0.5Nc=12q2qsNc>1NRN.


Заокруглення вгору може спричинити проблеми, не те, що його слід коли-небудь вибирати у присутності користувачів, що не підозрюють. Ось якийсь C99, який друкує "0\n1\n"на моїй машині.

#include <fenv.h>
#include <math.h>
#include <stdio.h>

int main(void) {
    double n = 10;
    double r = nextafter(1, 0);
    printf("%d\n", n == (n * r));
    fesetround(FE_UPWARD);
    printf("%d\n", n == (n * r));
}

Вибачте, я трохи повільно в ці дні - у мене виникають проблеми з отриманням частини нерівності
c2q2s2qs
Cade Roux

2qs

Дякую, я не був впевнений, чи є ще один крок, який я пропустив.
Кейд Ру
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.