Início rápido: tipos de dados BSON - Decimal128
Avalie esse Início rápido

Pense em quando você foi introduzido pela primeira vez ao conceito de decimais em cálculos numéricos. Resolvendo problemas de matemática ao longo das linhas de 3.231 / 1.28 causou problemas ao começar porque 1.28 não entra em 3.231 uniformemente. Isso faz com que uma longa string de números seja criada para fornecer uma resposta mais precisa. Em linguagens de programação, devemos escolher qual formato de número é correto dependendo da quantidade de precisão que precisamos. Quando se precisa de alta precisão ao trabalhar com tipos de dadosBSON, o
decimal128
é o único a usar.Como o nome sugere, o decimal128 fornece 128 bits de representação decimal para armazenar números realmente grandes (ou realmente pequenos) quando arredondar decimais exatamente é importante. O decimal128 suporta 34 dígitos decimais de precisão, ou significante, juntamente com um intervalo de expoente de -6143 a +6144. O significante não é normalizado no padrão de decimal128 permitindo múltiplas representações possíveis: 10 x 10^-1 = 1 x 10^0 = .1 x 10^1 = .01 x 10^2 e assim por diante. Ter a capacidade de armazenar valores máximos e mínimos na ordem de 10^6144 e 10^-6143, respectivamente, permite muita precisão.

Às vezes, ao fazer cálculos matemáticos de forma programática, os resultados são inesperados. Por exemplo, no Node.js:
1 > 0.1 2 0.1 3 > 0.2 4 0.2 5 > 0.1 * 0.2 6 0.020000000000000004 7 > 0.1 + 0.1 8 0.010000000000000002
Esse problema não é exclusivo do Node.js, em Java:
1 class Main { 2 public static void main(String[] args) { 3 System.out.println("0.1 * 0.2:"); 4 System.out.println(0.1 * 0.2); 5 } 6 }
Produz uma saída de:
1 0.1 * 0.2: 2 0.020000000000000004
Os mesmos cálculos em Python, Ruby, Rust e outros produzem os mesmos resultados. O que está acontecendo aqui? Essas linguagens são simplesmente ruins em matemática? Na verdade, os números binários de ponto flutuante simplesmente não são bons para representar valores básicos de 10. Por exemplo, o
0.1
usado nos exemplos acima é representado em binário como 0.0001100110011001101
.Para muitas situações, esse não é um grande problema. No entanto, em aplicativos monetários, a precisão é muito importante. Quem se lembra da questão de meio centavo do Superman 3? Quando a precisão e a exatidão são importantes para os cálculos, o decimal128 deve ser o tipo de dados escolhido.
No MongoDB, armazenar dados no formato decimal128 é relativamente simples com o construtor NumberDecimal():
1 NumberDecimal("9823.1297")
Passando o valor decimal como uma string, o valor é armazenado no banco de dados como:
1 NumberDecimal("9823.1297")
Se os valores forem passados como valores
double
:1 NumberDecimal(1234.99999999999)
Pode ocorrer perda de precisão no banco de dados:
1 NumberDecimal("1234.50000000000")
Outra consideração, além simplesmente do uso no MongoDB, é o uso e o suporte que sua programação tem para o decimal128. Muitos idiomas não oferecem suporte nativo a esse recurso e exigirão um plugin ou pacote adicional para obter a funcionalidade. Alguns exemplos...
Node.js: existem vários pacotes que fornecem suporte, como js-big-decimal ou node.js bigdecimal disponíveis no npm.
O campo
decimal128
surgiu em agosto 2009 como parte da revisão IEEE 754-2008 de pontos flutuantes. O MongoDB 3.4 foi quando o suporte para decimal128 apareceu pela primeira vez e, para usar o tipo de dados decimal
com o MongoDB, você deve usar uma versão do driver que ofereça suporte a esse ótimo recurso. Decimal128 é ótimo para números enormes (ou muito pequenos) e para quando a precisão nesses números é importante.