Pergunta

No meu curso, disseram-me:

Os valores contínuos são representaram aproximadamente na memória e, portanto, calcular com flutuadores envolve erros de arredondamento. Estes são pequenas discrepâncias nos padrões de bits; assim o e==f teste é inseguro se e e f são carros alegóricos.

Referindo-se a Java.

Isso é verdade? Eu usei declarações comparação com doubles e floats e nunca tive problemas de arredondamento. Nunca li num livro algo semelhante. Certamente a máquina virtual é responsável por isso?

Foi útil?

Solução

É verdade.

É uma limitação inerente de como flutuante valores de ponto são representados na memória em um número finito de bits.

Este programa, por exemplo, impressões "false":

public class Main {
  public static void main(String[] args) {
    double a = 0.7;
    double b = 0.9;
    double x = a + 0.1;
    double y = b - 0.1;
    System.out.println(x == y);
  }
}

Em vez de comparação exata com '==' você normalmente decidir sobre algum nível de precisão e perguntar se os números são "suficientemente próximo":

System.out.println(Math.abs(x - y) < 0.0001);

Outras dicas

Isso se aplica a Java tanto quanto para qualquer outra língua usando ponto flutuante. É inerente à concepção da representação de valores de ponto flutuante em hardware.

Mais informações sobre valores de ponto flutuante:

O que cada cientista computador deve saber sobre Floating-Point Arithmetic

Sim, o que representa 0,1 exatamente na base-2 é o mesmo que tentar representar 1/3 exatamente na base 10.

Isto é sempre verdadeiro. Existem alguns números, que não podem ser representadas com precisão usando a representação ponto flutuador. Considere, por exemplo, pi. Como você representar um número que tem infinitos dígitos, dentro de um armazenamento finito? Portanto, ao comparar números que você deve verificar se a diferença entre eles é menor, em seguida, alguns epsilon. Além disso, existem várias classes que existem que podem ajudar você a atingir uma maior precisão, como BigDecimal e BigInteger.

É certo. Note-se que Java não tem nada a ver com isso, o problema é inerente a matemática de ponto flutuante em ANY Idioma.

Muitas vezes você pode começar afastado com ele com problemas a nível de sala de aula, mas ele não está indo para o trabalho no mundo real. Às vezes, não vai funcionar na sala de aula.

Um incidente de há muito tempo de volta na escola. O professor de uma classe de introdução atribuído um problema exame final que estava provando um doozy real para muitos dos melhores alunos - que não estava funcionando e que não sabia por que. (Eu vi isso como um assistente de laboratório, eu não estava na classe.) Finalmente alguns começaram a me pedir ajuda e alguns sondagem revelou o problema:. Eles nunca tinha sido ensinado sobre a imprecisão inerente de matemática ponto flutuante

Agora, havia duas abordagens básicas para este problema, uma força bruta de um (que por acaso trabalhou neste caso, como ele fez os mesmos erros de cada vez) e um mais elegante (o que tornaria diferentes erros e não de trabalho. ) qualquer um que tentou a abordagem elegante teria atingido uma parede de tijolos, sem ter qualquer ideia porquê. Eu ajudei um monte deles e preso em um comentário explicando por que e em contactar-me se ele tinha perguntas.

Claro próximo semestre eu ouvi-lo sobre isso e eu basicamente pavimentado todo o departamento com um simples programa pouco:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

Apesar do que cada professor no departamento pensei, este irá terminar. A 3 milhões de sementes é simplesmente para torná-lo terminar mais rápido. (Se você não sabe o básico: Não há truques aqui, apenas esgotar a precisão de números de ponto flutuante).

Sim, como outras respostas disseram. Quero acrescentar que eu recomendo que você este artigo sobre precisão de ponto flutuante: visualizando flutua

A maioria CPUs (e linguagens de computador) uso IEEE 754 aritmética de ponto flutuante. Utilizando esta notação, há números decimais que não têm nenhuma representação exacta em esta notação, v.g. 0,1. Então, se você dividir 1 por 10 você não vai obter um resultado exato. Ao realizar vários cálculos em uma fileira, os erros resumir. Tente o seguinte exemplo em python:

>>> 0.1
0.10000000000000001
>>> 0.1 / 7 * 10 * 7 == 1
False

Isso não é realmente o que você esperaria matematicamente.

A propósito: Um equívoco comum sobre números de ponto flutuante é, que os resultados não são precisos e não pode ser comapared com segurança. Isso só é verdade se você realmente usar frações de números. Se toda a sua matemática está no domínio inteiro, duplos e carros alegóricos fazer exatamente o mesmo que ints e também pode ser comparado com segurança. Eles podem ser usados ??com segurança como contadores de loop, por exemplo.

Sim, Java também utiliza ponto flutuante aritmética.

Claro que é verdade. Pense nisso. Qualquer número deve ser representado em binário.

Imagem: "1000" como 0.5or 1/2, ou seja, 2 ** -1. Em seguida, "0100" é de 0,25 ou 1/4. Você pode ver onde estou indo.

Quantos números você pode representar desta maneira? 2 ** 4. Adicionando mais bits duplica o espaço disponível, mas nunca é infinito. 1/3 ou 1/10, para o assunto 1 / n, qualquer número que não seja múltiplo de 2 pode não ser realmente representados.

1/3 poderia ser "0101" (0,3125) ou "0110" (0.375). De qualquer valor se você multiplicar por 3, não será 1. Claro que você pode adicionar regras especiais. Digamos que você "quando você adiciona 3 vezes '0101', fazendo o 1" ... esta abordagem não vai funcionar no longo prazo. Você pode pegar alguns, mas então como sobre 1/6 vezes 2?

Não é um problema de representação binária, qualquer representação finita tem números que você não pode representar, eles são infinitos depois de tudo.

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