Zaokrąglanie zmiennoprzecinkowe

13

Czy liczba zmiennoprzecinkowa IEEE-754 <1 (tj. Generowana za pomocą generatora liczb losowych, który generuje liczbę> = 0,0 i <1,0) może być kiedykolwiek pomnożona przez jakąś liczbę całkowitą (w postaci zmiennoprzecinkowej), aby uzyskać liczbę równą lub większą niż ta liczba całkowita z powodu zaokrąglenia?

to znaczy

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

Może to być równoważne stwierdzeniu, że istnieje N i R, tak że jeśli R jest największą liczbą mniejszą niż 1, która może być reprezentowana w IEEE-754, to N * R> = N (gdzie * i> = są odpowiednie IEEE- 754 operatorów)

Wynika to z tego pytania opartego na tej dokumentacji i losowej funkcji postgresql

Cade Roux
źródło
Czy możesz powiedzieć coś o zakresie N, tj. Czy jest wystarczająco mały, aby być dokładnie reprezentowany w podwójnej precyzji IEEE-754?
Pedro
@Pedro W tym konkretnym przypadku tak, byłaby to mała liczba całkowita - tj. 10. Zakładam, że mówisz, że jeśli N jest bardzo dużą liczbą całkowitą z bardzo dużą liczbą cyfr znaczących, może nie być w stanie dokładnie przedstawić?
Cade Roux,
Dokładnie, jeśli , to f l ( R × f l ( N ) ) może być większy niż R Nfl(N)>Nfl(R×fl(N))RN .
Pedro

Odpowiedzi:

8

Zakładając, że zaokrąglenie do najbliższego i że , to zawsze N R < N zawsze. (Uważaj, aby nie przekonwertować liczby całkowitej, która jest zbyt duża).N>0NR<N

Niech , gdzie c [ 1 , 2 ) jest znaczeniem, a q jest wykładnikiem liczby całkowitej. Niech 1 - 2 - s = R i wyprowadź granicęc2q=Nc[1,2)q12s=R

NR=c2q(12s)c2q2qs,

c=1N2qs0.5Nc=12q2qsNc>1NRN.


Zaokrąglanie w górę może powodować problem, nie dlatego, że należy go zawsze wybierać w obecności niczego niepodejrzewających użytkowników. Oto niektóre C99, które drukuje "0\n1\n"na moim komputerze.

#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));
}
Tyrone
źródło
c2q2s2qs
2qs
Dzięki, nie byłem pewien, czy brakuje mi jeszcze jednego kroku.
Cade Roux,