Gleitkomma-Rundung

13

Kann eine IEEE-754-Gleitkommazahl <1 (dh mit einem Zufallsgenerator generiert, der eine Zahl> = 0.0 und <1.0 generiert) jemals mit einer ganzen Zahl (in Gleitkommaform) multipliziert werden, um eine Zahl gleich oder größer als zu erhalten? diese ganze Zahl wegen der Rundung?

dh

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

This might be equivalent to saying that does there exist an N and R such that if R is the largest number less than 1 which can be represented in IEEE-754 then N * R >= N (where * and >= are appropriate IEEE-754 operators)

This comes from this question based on this documentation and the postgresql random function

Cade Roux
quelle
Can you say anything about the range of N, i.e. is it small enough to be represented exactly in IEEE-754 double-precision?
Pedro
@Pedro In this particular case, yes, it would be a small integer - i.e. 10. I assume you are saying that if N is a very large integer with a very large number of significant digits it might not be able to be represented exactly?
Cade Roux
Exactly, if fl(N)>N, then fl(R×fl(N)) may be larger than RN.
Pedro

Antworten:

8

Assuming round-to-nearest and that N>0, then NR<N always. (Be careful not to convert an integer that's too large.)

Let c2q=N, where c[1,2) is the significand and q is the integer exponent. Let 12s=R and derive the bound

NR=c2q(12s)c2q2qs,

with equality if and only if c=1. The right-hand side is less than N and, since 2qs is exactly 0.5 units in the last place of N, either c=1 and 2q2qs is exactly representable (since N is normal and not the smallest normal), or c>1, and the nearest rounding is down. In both cases, NR is less than N.


Upward rounding can cause a problem, not that it should ever be selected in the presence of unsuspecting users. Here's some C99 that prints "0\n1\n" on my 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));
}
Tyrone
quelle
I'm sorry, I'm a little slow these days - I'm having trouble getting the part of the inequality
c2q2s2qs
Cade Roux
@Cade Apparently I can't do algebra today. I meant 2qs.
Tyrone
Thanks, I wasn't sure if there was another step I was missing.
Cade Roux