Quando usar float vs decimal


14

Estou criando esta API e o banco de dados armazenará valores que representam um dos seguintes:

  • percentagem
  • média
  • taxa

Sinceramente, não tenho idéia de como representar algo que o intervalo esteja entre 0 e 100% em números. Deveria ser

  • 0,00 - 1,00
  • 0,00 - 100,00
  • qualquer outra alternativa que eu não conheça

Existe uma escolha clara para isso? Uma maneira global de representar nos bancos de dados algo que varia de 0 a 100% por cento? Indo além, qual é o tipo correto para ele, float ou decimal?

Obrigado.



5
Os números podem ser armazenados de várias maneiras. Não há nada inerentemente errado em armazenar uma porcentagem usando 0-100 ou 0-1. O que importa é o que você precisa fazer com os números, qual a precisão que precisa e assim por diante. Você deve explicar mais contexto antes que uma boa resposta possa ser dada. Você precisa armazenar números que sejam exatamente representáveis ​​com um pequeno número de dígitos decimais? Se você mede as coisas, obtém frações como terços ou sétimos. Você precisa armazenar exatamente? Ou apenas aproximadamente? Quanto aproximadamente? O que você fará com eles?
Eric Postpischil 22/01

11
Se os valores forem de 0,00 a 100,00 nas etapas de 0,01, são 10001 valores diferentes. Simplesmente use a intpara representar centésimos ou em unidades de Permyriad ou ‱.
chux - Restabelece Monica

@ chux-ReinstateMonica - Sim, "números inteiros em escala" são possíveis, mas desajeitados.
Rick James

@RickJames Talvez. Não encontrei números inteiros difíceis.
chux - Restabelece Monica

Respostas:


4

Eu vou tomar a posição oposta.

FLOATé para números aproximados, como porcentagens, médias etc. Você deve formatar ao exibir os valores, no código do aplicativo ou usando a FORMAT()função do MySQL.

Nunca teste float_value = 1.3; existem muitas razões pelas quais isso irá falhar.

DECIMALdeve ser usado para valores monetários. DECIMALevita um segundo arredondamento quando um valor precisa ser arredondado para dólares / centavos / euros / etc. Contadores não gostam de frações de centavos.

A implementação do MySQL DECIMALpermite 65 dígitos significativos; FLOATdá cerca de 7 e DOUBLEcerca de 16. 7 geralmente é mais que suficiente para sensores e cálculos científicos.

Quanto à "porcentagem" - às vezes eu uso TINYINT UNSIGNEDquando quero consumir apenas 1 byte de armazenamento e não preciso de muita precisão; às vezes eu usei FLOAT(4 bytes). Não há tipo de dados ajustado especificamente para porcentagem. (Observe também que isso DECIMAL(2,0)não pode conter o valor 100, portanto, tecnicamente, você precisaria DECIMAL(3,0).)

Ou, às vezes, usei um FLOATque mantinha um valor entre 0 e 1. Mas, então, precisaria me certificar de multiplicar por 100 antes de exibir a "porcentagem".

Mais

Todos os três "percentual, média, taxa" cheiram a carros alegóricos, então essa seria minha primeira escolha.

Um critério para decidir sobre o tipo de dados ... Quantas cópias do valor existirão?

Se você tiver uma tabela de bilhões de linhas com uma coluna para uma porcentagem, considere que TINYINTisso levaria 1 byte (total de 1 GB), mas FLOATlevaria 4 bytes (total de 4 GB). OTOH, a maioria dos aplicativos não possui muitas linhas, portanto isso pode não ser relevante.

Como regra geral, valores "exatos" devem usar alguma forma de INTou DECIMAL. Coisas inexatas (cálculos científicos, raízes quadradas, divisão, etc.) devem usar FLOAT(ou DOUBLE).

Além disso, a formatação da saída geralmente deve ser deixada para o front end do aplicativo. Ou seja, mesmo que uma "média" possa ser calculada como "14.6666666 ...", a exibição deve mostrar algo como "14.7"; isso é mais amigável para os seres humanos. Enquanto isso, você tem o valor subjacente para decidir posteriormente que "15" ou "14.667" é a formatação de saída preferível.

O intervalo "0,00 - 100,00" pode ser feito com FLOAT e usar a formatação de saída ou com DECIMAL(5,2)(3 bytes) com a pré-determinação de que você sempre desejará a precisão indicada .


3

Eu geralmente recomendaria contra o uso float. Os números de ponto flutuante representam números na base 2, o que faz com que alguns números (exatos) sejam arredondados em operações ou comparações, porque eles simplesmente não podem ser armazenados com precisão na base 2. Isso pode levar a comportamentos surpreendentes.

Considere o seguinte exemplo :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

A comparação da base 2 do número 1.3falha. Isso é complicado.

Em comparação, o decimal fornece uma representação precisa de números finitos dentro de seu intervalo. Se você mudar floatpara decimal(2, 1)no exemplo acima, obtém os resultados esperados.


4
Esta resposta é falsa em vários aspectos. “Em comparação, os decimais têm um intervalo menor, mas fornecem uma representação exata dos números finitos dentro desse intervalo” é falso: o decimal não representa exatamente. "Alguns números (exatos, finitos) são arredondados" está incorreto; números não são "arredondados". Conversões e outras operações podem ser arredondadas. O modo de arredondamento padrão é mais comumente arredondar para o mais próximo, até arredondar para cima, e não arredondar para cima.
Eric Postpischil 22/01

4
Problemas com precisão não são devidos a “números de ponto flutuante”, mas simplesmente devido a representações numéricas: todas as representações numéricas finitas têm precisão limitada: ponto flutuante, ponto fixo, inteiro, racional, decimal, binário, tudo.
Eric Postpischil 22/01

2
Suspiro. O que você consertou? Meu comentário diz que a resposta está errada porque diz que decimal fornece uma representação exata dos números dentro de seu intervalo, mas, na verdade, não fornece porque não fornece uma representação exata de ⅓. A mudança diz "preciso" em vez de "exato", mas então por que o ponto flutuante binário não é tão bom - nem exato para ⅓ e ambos ou nenhum deles é preciso, dependendo de qual é o seu limite de precisão e quanta precisão eles têm. A pergunta indica que as médias serão representadas, e a média de três coisas fornece números como ⅓.
Eric Postpischil 22/01

4
O comentário diz que o arredondamento para o mais próximo é o mais usado, mas a resposta ainda diz arredondamento. A resposta diz que as comparações podem ser arredondadas, mas a comparação é perfeita: as comparações sempre retornam um resultado matematicamente correto, sem arredondamentos. (Algumas linguagens de programação podem converter operandos antes de comparar, mas essas são operações separadas.)
Eric Postpischil

11
1/3 não pode ser representado exatamente em binário ou decimal. Um desconto de 20% em US $ 14,99 exigirá que não existam centavos fracionários de arredondamento.
Rick James

0

A diferença entre float e decimal é a precisão. Decimal pode 100% representar com precisão qualquer número dentro da precisão do formato decimal, enquanto que Float não pode representar com precisão todos os números.

Use decimal para, por exemplo, valor relacionado financeiro e use float para, por exemplo, valor gráfico relacionado


0

Eu recomendo usar decimal(5,2)se você deseja armazená-lo da mesma maneira que o exibirá, pois decimalé para preservar a precisão exata. (Consulte https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

Como os valores de ponto flutuante são aproximados e não são armazenados como valores exatos, as tentativas de tratá-los como exatos nas comparações podem levar a problemas. Eles também estão sujeitos a dependências de plataforma ou implementação.

( https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html )

Um valor de ponto flutuante, conforme escrito em uma instrução SQL, pode não ser o mesmo que o valor representado internamente.

Para colunas DECIMAIS, o MySQL executa operações com uma precisão de 65 dígitos decimais, o que deve resolver os problemas mais comuns de imprecisão.

https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html


0

Decimal: no caso de aplicativos financeiros, é melhor usar os tipos decimais, pois oferece um alto nível de precisão e é fácil evitar erros de arredondamento.

Duplo: tipos duplos são provavelmente o tipo de dados mais normalmente usado para valores reais, exceto manipular dinheiro.

Flutuar: É usado principalmente em bibliotecas gráficas, porque demandas muito altas de poderes de processamento também usavam situações que podem suportar erros de arredondamento.

Referência: http://net-informations.com/q/faq/float.html


0
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G

*********************************************************************

@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

O decimal fez exatamente o que deveria ser feito nesses casos, truncou o restante, perdendo a parte 1/3.

Portanto, para somas, o decimal é melhor, mas para divisões, o float é melhor, até certo ponto, é claro. Quero dizer, usar DECIMAL não fornecerá "aritmética à prova de falhas" de nenhuma maneira.

Espero que isso ajude.


0

Em tsql: Float, 0.0 armazena como 0 e não é necessário definir após o dígito decimal, por exemplo, você não precisa escrever Float (4,2). Decimal, 0,0 armazena como 0,0 e tem opção para definir como decimal (4,2), sugiro 0,00-1,00. Ao fazer isso, você pode calcular o valor dessa porcentagem sem multiplicar por 100 e, se informar, defina o tipo de dados dessa coluna em porcentagem, como o MS Excel e outras plataformas 0.5 -> 50%.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.