Arrotondamento in virgola mobile


13

Un IEEE-754 numero in virgola mobile <1 (ovvero generato con un generatore di numeri casuali che genera un numero> = 0,0 e <1,0) può mai essere moltiplicato per un numero intero (in forma di virgola mobile) per ottenere un numero uguale o maggiore di che numero intero a causa di arrotondamento?

vale a dire

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

Ciò potrebbe equivalere a dire che esiste un N e un R tali che se R è il numero più grande inferiore a 1 che può essere rappresentato in IEEE-754, allora N * R> = N (dove * e> = sono IEEE appropriati- 754 operatori)

Questo deriva da questa domanda basata su questa documentazione e sulla funzione casuale postgresql


Puoi dire qualcosa sulla gamma di N, ovvero è abbastanza piccola da essere rappresentata esattamente nella doppia precisione IEEE-754?
Pedro

@Pedro In questo caso particolare, sì, sarebbe un numero intero piccolo - cioè 10. Suppongo che stai dicendo che se N è un numero intero molto grande con un numero molto grande di cifre significative, potrebbe non essere possibile rappresentare esattamente?
Cade Roux,

Esattamente, se , allora f l ( R × f l ( N ) ) può essere maggiore di R N . fl(N)>Nfl(R×fl(N))RN
Pedro,

Risposte:


8

Supponendo che sia arrotondato al più vicino e che , quindi N R < N sempre. (Fare attenzione a non convertire un numero intero troppo grande.)N>0NR<N

Sia , dove c [ 1 , 2 ) è il significato e q è l'esponente intero. Lasciate 1 - 2 - s = R e derivate il limitec2q=Nc[1,2)q12s=R

NR=c2q(12s)c2q2qs,

con uguaglianza se e solo se . Il lato destro è inferiore a N e, poiché 2 - q - s è esattamente 0,5 unità nell'ultimo posto di N , c = 1 e 2 - q - 2 - q - s è esattamente rappresentabile (poiché N è normale e non il più piccolo normale) o c > 1 e il arrotondamento più vicino è in basso. In entrambi i casi, N R è inferiore a Nc=1N2qs0.5Nc=12q2qsNc>1NRN.


L'arrotondamento verso l'alto può causare un problema, non che debba mai essere selezionato in presenza di utenti ignari. Ecco un po 'di C99 che stampa "0\n1\n"sulla mia macchina.

#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 Apparentemente non posso fare algebra oggi. volevo dire2-q-S.
Tyrone,

Grazie, non ero sicuro che ci fosse un altro passo che mi mancava.
Cade Roux,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.