Numpy: DOC: docstring para numpy.finfo.eps está incorreto

Criado em 5 jan. 2016  ·  5Comentários  ·  Fonte: numpy/numpy

A docstring para numpy.finfo atualmente define o atributo eps como:

O menor número positivo representável tal que 1,0 + eps! = 1,0. [...]

Essa definição não é correta, pelo menos no caso comum dos formatos binários IEEE 754. Por exemplo, com o formato binário64 IEEE 754 sob o modo usual de arredondamento round-tie-to-even, a definição declarada fornece um valor de 2**-53 + 2**-105 (aprox. 1.1102230246251568e-16 ), que é um pouco mais da metade do valor correto de 2**-52 (aproximadamente 2.220446049250313e-16 ).

In [36]: eps = 2**-53 + 2**-105

In [37]: eps
Out[37]: 1.1102230246251568e-16

In [38]: 1.0 + eps != 1.0
Out[38]: True

In [39]: 1.0 + np.nextafter(eps, -np.inf) != 1.0
Out[39]: False

In [40]: np.finfo(float).eps
Out[40]: 2.2204460492503131e-16

Algumas reformulações possíveis:

O menor número positivo como 1.0 + eps é representável.

Ou:

A diferença entre 1,0 e o menor float representável maior que 1,0.

Ou pode ser definido em termos de nextafter como:

O valor de np.nextafter(1.0, np.inf) - 1.0 .

Para comparação, a seção 5.2.4.2.2, parágrafo 11 do padrão C99 define as várias macros *_EPSILON ( DBL_EPSILON , FLT_EPSILON , ...) como:

a diferença entre 1 e o menor valor maior que 1 que é representável no tipo de ponto flutuante fornecido, b 1− p

A docstring para epsneg está igualmente incorreta.

00 - Bug Triaged Documentation

Comentários muito úteis

Aqui estamos quase 4 anos depois e isso não foi corrigido. Não acho que https://github.com/numpy/numpy/pull/14618 será suficiente para encerrar este problema.

Para esclarecer o relatório de bug, a definição atual de eps na docstring está desviada por um fator de 2 do valor de eps retornado por np.finfo. (Os números que dou abaixo são para implementações com o padrão de ponto flutuante IEEE-754 de 64 bits).

np.finfo (1.0) .eps = 2 ** - 52 = 2,220446049250313e-16

No entanto, o docstring define eps como

"O menor número positivo representável tal que 1,0 + eps! = 1,0."

O valor real de eps que satisfaria a definição 1.0 + eps_min! = 1.0 é:

eps_min = 2 -53 + 2 -105 = 1,1102230246251568e-16

que é quase metade do valor presente de np.finfo (1.0) .eps. Provavelmente não queremos alterar o valor de np.finfo (1.0) .eps, para manter a compatibilidade com versões anteriores, mas a definição de docstring de eps precisa ser corrigida para corresponder ao que é calculado. O código-fonte para np.finfo (1.0) eps usa numpy.MachAr, e olhando a documentação lá, que permite outras bases além de 2, acho que a melhor definição de eps é uma das primeiras opções que @mdickinson sugeriu anteriormente. Eu também adicionaria um valor de exemplo à descrição:

"A diferença entre 1,0 e a menor flutuação representável maior que 1,0. (Para flutuações binárias de 64 bits no padrão IEEE-754, eps = 2 ** - 52 ≅ 2,22e-16.)"

A docstring para epsneg está igualmente incorreta.

Todos 5 comentários

Ah, olhando para a fonte , vejo que eps é realmente calculado como a menor _poder de 2_ tal que 1 + eps != eps . Isso não é a mesma coisa que a diferença entre 1.0 e o próximo float representável acima de 1.0 , embora as duas coisas aconteçam coincidir para IEEE 754 e o arredondamento round-tie-to-even modo. Portanto, minhas reformulações sugeridas acima são inválidas. Talvez algo como:

A menor potência de 2, que 1.0 + eps é representável.

seria melhor? Tecnicamente, esse 2 deve ser substituído pelo radical de ponto flutuante, mas isso provavelmente é desnecessariamente pedante. O NumPy atualmente tem suporte para radix 10 ou radix 16 floats?

[À parte, prefiro muito mais a definição de epsilon no estilo C99, uma vez que envolve apenas o formato e não depende da semântica da adição de ponto flutuante Em particular, a definição C99 não depende do modo de arredondamento atualmente em vigor, enquanto a definição 1 + eps != 1 sim.]

Um ponteiro para np.spacing e np.nextafter na seção "Consulte também" também seria potencialmente útil.

Aqui estamos quase 4 anos depois e isso não foi corrigido. Não acho que https://github.com/numpy/numpy/pull/14618 será suficiente para encerrar este problema.

Para esclarecer o relatório de bug, a definição atual de eps na docstring está desviada por um fator de 2 do valor de eps retornado por np.finfo. (Os números que dou abaixo são para implementações com o padrão de ponto flutuante IEEE-754 de 64 bits).

np.finfo (1.0) .eps = 2 ** - 52 = 2,220446049250313e-16

No entanto, o docstring define eps como

"O menor número positivo representável tal que 1,0 + eps! = 1,0."

O valor real de eps que satisfaria a definição 1.0 + eps_min! = 1.0 é:

eps_min = 2 -53 + 2 -105 = 1,1102230246251568e-16

que é quase metade do valor presente de np.finfo (1.0) .eps. Provavelmente não queremos alterar o valor de np.finfo (1.0) .eps, para manter a compatibilidade com versões anteriores, mas a definição de docstring de eps precisa ser corrigida para corresponder ao que é calculado. O código-fonte para np.finfo (1.0) eps usa numpy.MachAr, e olhando a documentação lá, que permite outras bases além de 2, acho que a melhor definição de eps é uma das primeiras opções que @mdickinson sugeriu anteriormente. Eu também adicionaria um valor de exemplo à descrição:

"A diferença entre 1,0 e a menor flutuação representável maior que 1,0. (Para flutuações binárias de 64 bits no padrão IEEE-754, eps = 2 ** - 52 ≅ 2,22e-16.)"

A docstring para epsneg está igualmente incorreta.

Eu também tropecei nessa imprecisão. Isso deve ser consertado.

Para referência, o Matlab documenta seu eps (que tem o mesmo valor) como: "a distância de 1,0 até o próximo número de precisão dupla maior, ou seja, 2 ^ -52."

A definição atual está incorreta e confusa devido a problemas de arredondamento. @gwhammett a definição proposta é correta e mais descritiva e incentiva um RP a encerrar este problema.

Esta página foi útil?
0 / 5 - 0 avaliações