Redondeo de punto flotante

13

¿Se puede multiplicar un número de punto flotante IEEE-754 <1 (es decir, generado con un generador de números aleatorios que genera un número> = 0.0 y <1.0) por algún número entero (en forma de punto flotante) para obtener un número igual o mayor que ese entero debido al redondeo?

es decir

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

Esto podría ser equivalente a decir que existe un N y R tales que si R es el número más grande menor que 1 que puede representarse en IEEE-754, entonces N * R> = N (donde * y> = son IEEE- apropiados 754 operadores)

Esto viene de esta pregunta basada en esta documentación y la función aleatoria postgresql

Cade Roux
fuente
¿Puede decir algo sobre el rango de N, es decir, es lo suficientemente pequeño como para ser representado exactamente en IEEE-754 de doble precisión?
Pedro
@Pedro En este caso particular, sí, sería un número entero pequeño, es decir, 10. Supongo que está diciendo que si N es un número entero muy grande con un número muy grande de dígitos significativos, ¿es posible que no pueda representarse exactamente?
Cade Roux
Exactamente, si , entonces f l ( R × f l ( N ) ) puede ser mayor que R N . fl(N)>Nfl(R×fl(N))RN
Pedro

Respuestas:

8

Suponiendo redondear al más cercano y que , entonces N R < N siempre. (Tenga cuidado de no convertir un número entero que sea demasiado grande).N>0NR<N

Sea , donde c [ 1 , 2 ) es el significado y q es el exponente entero. Deje 1 - 2 - s = R y derive el límitec2q=Nc[1,2)q12s=R

NR=c2q(12s)c2q2qs,

con igualdad si y solo si . El lado derecho es menor que N y, dado que 2 - q - s es exactamente 0.5 unidades en el último lugar de N , c = 1 y 2 - q - 2 - q - s es exactamente representable (ya que N es normal y no el más pequeño normal), o c > 1 , y el redondeo más cercano está abajo. En ambos casos, N R es menor que Nc=1N2qs0.5Nc=12q2qsNc>1NRN.


El redondeo ascendente puede causar un problema, no siempre que deba seleccionarse en presencia de usuarios desprevenidos. Aquí hay algunos C99 que se imprimen "0\n1\n"en mi máquina.

#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
fuente
Lo siento, estoy un poco lento en estos días - Tengo problemas para entender la desigualdad
c2q2s2qs
Cade Roux
2qs
Gracias, no estaba seguro de si faltaba otro paso.
Cade Roux