Pergunta

Eu tropecei em um bug muito estranho. Leia os comentários no código para ver o que é exatamente o bug, mas essencialmente um módulo 1 variável está retornando 1 (mas não é igual a 1!). Suponho que haja um problema de exibição em que o flutuador está extremamente próximo de um, mas não exatamente. No entanto, deve ser modular para zero. Não posso testar este caso facilmente porque (último % 1)! = 1,0! Quando tento conectar os mesmos números em outro terminal Python, tudo se comporta corretamente. O que está acontecendo?

def r(k,i,p):
    first = i*p
    last = first + p

    steps = int((i+1)*p) - int(i*p)
    if steps < 1:
        return p
    elif steps >= 1:
        if k == 0:
            return 1 - (first % 1)
        elif k == steps:
            if i == 189:
                print last, 1, type(last), last % 1, last - int(last)
                # Prints: 73.0 1 <type 'float'> 1.0 1.0
                print last % 1 == 1 # Returns False
            if last % 1 == 1.0:
                return 0
            return (last % 1)
        else:
            return 1
Foi útil?

Solução

Bem -vindo ao IEEE754, Aproveite sua estadia.

Outras dicas

A impressão não mostra toda a precisão do número como armazenado, você pode usar repr() fazer isso

>>> last=72.99999999999999
>>> print last, 1, type(last), last % 1, last - int(last)
73.0 1 <type 'float'> 1.0 1.0
>>> print last % 1 == 1
False
>>> print repr(last), 1, type(last), repr(last%1), repr(last - int(last))
72.999999999999986 1 <type 'float'> 0.99999999999998579 0.99999999999998579
>>> 

Você deve usar o math.fmod (x, y). Aqui está um trecho de http://docs.python.org/library/math.html:

"Observe que a expressão de python x % y pode não retornar o mesmo resultado. A intenção do padrão C é que Fmod (x, y) seja exatamente (matematicamente; para infinita precisão) igual a x - n*y para algum número inteiro n de modo que o resultado tenha o mesmo sinal que x e magnitude menor que o ABS (Y). O X % y do Python retorna um resultado com o sinal de Y, e pode não ser exatamente computável para argumentos de flutuação. Por exemplo, FMOD (-1e -100, 1E100) é -1e-100, mas o resultado do -1e-100 % 1E100 do Python é 1E100-1E-100, que não pode ser representado exatamente como um flutuador, e Rodadas para o surpreendente 1E100. Por esse motivo, a função fmod () é geralmente preferida ao trabalhar com carros alegóricos, enquanto o X % Y do Python é preferido ao trabalhar com números inteiros ".

Você poderia tentar o Math.fmod função em vez de last % 1, talvez seja mais adequado para o seu problema. Ou você pode reformular seu problema no espaço inteiro.

De qualquer forma, não é uma boa prática comparar valores de flutuação usando a igualdade == operador, devido a resultados imprecisos, mesmo de operações parecidas triviais como 0.1 + 0.2 == 0.3

Se você precisa de precisão arbitrária, existem alguns projetos por aí que fazem exatamente isso. GMPY lida com números inteiros multi-precisão, mpmath que parece muito bom e bigfloat que envolve mpfr. O que você tem pode ser suficiente através da resposta de Gnibbler, mas, por precaução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top