Arrondi en virgule flottante


13

Un nombre à virgule flottante IEEE-754 <1 (c'est-à-dire généré avec un générateur de nombres aléatoires qui génère un nombre> = 0,0 et <1,0) peut-il être multiplié par un entier (sous forme de virgule flottante) pour obtenir un nombre égal ou supérieur à cet entier en raison de l'arrondi?

c'est à dire

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

Cela pourrait être équivalent à dire qu'il existe un N et R tels que si R est le plus grand nombre inférieur à 1 qui peut être représenté dans IEEE-754 alors N * R> = N (où * et> = sont appropriés IEEE- 754 opérateurs)

Cela vient de cette question basée sur cette documentation et la fonction aléatoire postgresql


Pouvez-vous dire quelque chose sur la plage de N, c'est-à-dire qu'elle est suffisamment petite pour être représentée exactement dans la double précision IEEE-754?
Pedro

@Pedro Dans ce cas particulier, oui, ce serait un petit entier - c'est-à-dire 10. Je suppose que vous dites que si N est un très grand entier avec un très grand nombre de chiffres significatifs, il pourrait ne pas être représenté exactement?
Cade Roux

Exactement, si , alors peut être plus grand que . f l ( R × f l ( N ) ) R Nfl(N)>Nfl(R×fl(N))RN
Pedro

Réponses:


8

En supposant arrondir au plus proche et que , alors toujours. (Veillez à ne pas convertir un entier trop grand.)N R < NN>0NR<N

Soit , où est la signification et est l'exposant entier. Soit et dériver la bornec [ 1 , 2 ) q 1 - 2 - s = Rc2q=Nc[1,2)q12s=R

NR=c2q(12s)c2q2qs,

avec égalité si et seulement si . Le côté droit est inférieur à et, puisque est exactement unité à la dernière place de , soit et est exactement représentable (puisque est normal et non la plus petite normale), ou , et l'arrondi le plus proche est vers le bas. Dans les deux cas, est inférieur à .c=1N2qs0.5Nc=12q2qsNc>1NRN


L'arrondi à la hausse peut poser un problème, non qu'il doive jamais être sélectionné en présence d'utilisateurs sans méfiance. Voici du C99 qui imprime "0\n1\n"sur ma machine.

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

Je suis désolé, je suis un peu lent ces jours-ci - j'ai du mal à obtenir la part de l'inégalité
c2q2s2qs
Cade Roux

@Cade Apparemment, je ne peux pas faire d'algèbre aujourd'hui. Je voulais dire . 2qs
Tyrone

Merci, je ne savais pas s'il y avait une autre étape qui me manquait.
Cade Roux
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.