Arredondamento de ponto flutuante

13

Um número de ponto flutuante IEEE-754 <1 (ou seja, gerado com um gerador de números aleatórios que gera um número> = 0,0 e <1,0) pode ser multiplicado por algum número inteiro (na forma de ponto flutuante) para obter um número igual ou maior que esse número inteiro devido ao arredondamento?

ie

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

Isso pode ser equivalente a dizer que existe um N e R tal que, se R for o maior número menor que 1, que pode ser representado no IEEE-754, então N * R> = N (onde * e> = são apropriados IEEE- 754 operadores)

Isso vem desta pergunta com base nesta documentação e na função aleatória postgresql

Cade Roux
fonte
Você pode dizer algo sobre o intervalo de N, ou seja, é pequeno o suficiente para ser representado exatamente na precisão dupla IEEE-754?
Pedro
@Pedro Nesse caso em particular, sim, seria um número inteiro pequeno - ou seja, 10. Suponho que você esteja dizendo que se N é um número inteiro muito grande com um número muito grande de dígitos significativos, pode não ser possível representar exatamente?
Cade Roux
Precisamente, se , então f l ( R × f l ( N ) ) podem ser maiores que R N . feu(N)>Nfeu(R×feu(N))RN
Pedro

Respostas:

8

Supondo que o arredondamento é o mais próximo e que , então N R < N sempre. (Cuidado para não converter um número inteiro muito grande.)N>0 0NR<N

Seja , onde c [ 1 , 2 ) é o significando e q é o expoente inteiro. Seja 1 - 2 - s = R e derivar o limitec2-q=Nc[1,2)q1-2-s=R

NR=c2-q(1-2-s)c2-q-2-q-s,

com igualdade se e somente se . O lado direito é menor que N e, como 2 - q - s é exatamente 0,5 unidades no último lugar de N , c = 1 e 2 - q - 2 - q - s é exatamente representável (uma vez que N é normal e não o menor normal), ou c > 1 , e o arredondamento mais próximo é baixo. Nos dois casos, N R é menor que Nc=1N2-q-s0,5Nc=12-q-2-q-sNc>1NRN.


O arredondamento para cima pode causar um problema, mas nunca deve ser selecionado na presença de usuários inocentes. Aqui está uma C99 impressa "0\n1\n"na minha 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
fonte
Me desculpe, eu sou um pouco lento estes dias - Estou tendo problemas para obter a parte da desigualdade
-c2-q2-s-2-qs
Cade Roux
2-q-s
Obrigado, eu não tinha certeza se havia outro passo que estava faltando.
Cade Roux