Pergunta

Eu encontrei um problema introduzindo colunas de ponto flutuante no esquema de banco de dados MySQL de que as comparações nos valores de ponto flutuante não retornam sempre os resultados corretos.

1 - 50.12
2 - 34.57
3 - 12.75
4 - ... (descanse tudo menos de 12,00)

SELECT COUNT(*) FROM `users` WHERE `points` > "12.75"

Isso me retorna "3".

Eu li que as comparações dos valores de ponto flutuante no MySQL são uma má idéia e o tipo decimal é a melhor opção.

Tenho alguma esperança de avançar com o tipo de flutuação e fazer com que as comparações funcionem corretamente?

Foi útil?

Solução

Você percebe o problema abaixo?

CREATE TABLE a (num float);

INSERT INTO a VALUES (50.12);
INSERT INTO a VALUES (34.57);
INSERT INTO a VALUES (12.75);
INSERT INTO a VALUES (11.22);
INSERT INTO a VALUES (10.46);
INSERT INTO a VALUES (9.35);
INSERT INTO a VALUES (8.55);
INSERT INTO a VALUES (7.23);
INSERT INTO a VALUES (6.53);
INSERT INTO a VALUES (5.15);
INSERT INTO a VALUES (4.01);

SELECT SUM(num) FROM a;
+-----------------+
| SUM(num)        |
+-----------------+
| 159.94000005722 | 
+-----------------+

Há um extra 0.00000005722 espalhe entre algumas dessas linhas. Portanto, alguns desses valores retornarão falsos quando comparados com o valor com o qual foram inicializados.

Para evitar problemas com aritmética e comparações de ponto flutuante, você deve usar o DECIMAL tipo de dados:

ALTER TABLE a MODIFY num DECIMAL(6,2);

SELECT SUM(num) FROM a;
+----------+
| SUM(num) |
+----------+
|   159.94 | 
+----------+
1 row in set (0.00 sec)

Outras dicas

Eu enfrentei o problema semelhante uma vez. Converta o campo 'flutuante' em 'decimal'. Definitivamente, resolverá o problema.

Eu faço isso

WHERE abs(value - 12.75)<0.001

Mas eu concordo, qualquer idioma pode comparar a igualdade de flutuação e, se os valores armazenados forem igual a números exatos valores que você inseriu, não deve haver nenhum problema

Com apenas alguns decimais e valores de correspondência exata, os erros de precisão não parecem um motivo óbvio para tais incompatibilidades no MySQL

É um ponto flutuante, então qual é o problema? 3 pode ser o resultado correto, depende do que o banco de dados pensa em 12,75. São 12,75 ou apenas um pouco mais?

Use decimal se desejar números exatos.

Há problemas com a comparação de carros alegóricos para a igualdade. Isso pode dar resultados imprevisíveis. Isso se deve à implementação interna da aritmética do ponto flutuante.

Comparando um número com uma string?

Use real em vez de flutuar ou decimal.

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