DEV Community

Lucas Pereira de Souza
Lucas Pereira de Souza

Posted on

Decimal: futuro tipo numérico do JavaScript

logotech

## Decimal: A Necessidade de Precisão em JavaScript e o Futuro com TC39

A computação, em sua essência, lida com números. No entanto, a forma como representamos e manipulamos esses números pode ter implicações profundas, especialmente em domínios onde a precisão é crucial, como em aplicações financeiras, científicas ou de engenharia. O JavaScript, historicamente, tem enfrentado desafios nessa área com sua representação nativa de números de ponto flutuante, abrindo a porta para a necessidade de tipos de dados mais precisos como o Decimal.

O Problema com Ponto Flutuante em JavaScript

O JavaScript utiliza o padrão IEEE 754 para representar números de ponto flutuante de dupla precisão (64 bits). Embora eficiente para a maioria dos casos de uso, essa representação pode levar a imprecisões sutis em certas operações. A razão fundamental reside na forma como números decimais são convertidos para binário. Muitos números decimais que parecem simples em base 10 (como 0.1 ou 0.2) não possuem uma representação binária finita exata. Isso resulta em pequenas discrepâncias que podem se acumular e causar erros inesperados.

Considere um exemplo clássico:

// Exemplo em JavaScript puro
let result = 0.1 + 0.2;
console.log(result); // Saída: 0.30000000000000004
Enter fullscreen mode Exit fullscreen mode

Essa saída, 0.30000000000000004, em vez do esperado 0.3, demonstra o problema inerente à representação de ponto flutuante. Em aplicações financeiras, onde centavos importam, esse tipo de imprecisão é inaceitável.

A Ascensão do Decimal e o Status da TC39

Para mitigar esses problemas, bibliotecas de Decimal surgiram como soluções populares. Essas bibliotecas implementam números decimais usando representações internas que garantem a precisão exata, geralmente armazenando os números como strings ou arrays de dígitos.

No entanto, a necessidade de uma solução nativa e padronizada levou a propostas para inclusão de um tipo Decimal na especificação ECMAScript (a base do JavaScript). A proposta para um tipo Decimal alcançou o estágio 2 (Working Draft) do processo de padronização da TC39 (Technical Committee 39), o comitê responsável pela evolução do ECMAScript. Isso significa que a proposta está sendo ativamente desenvolvida e revisada, com o objetivo de se tornar um recurso padrão da linguagem.

O status atual da proposta indica um caminho promissor para a adição nativa de um tipo Decimal, o que simplificaria o desenvolvimento e eliminaria a dependência de bibliotecas externas para muitos casos de uso.

Comparando Decimal com BigInt

É importante não confundir Decimal com BigInt. Enquanto ambos abordam limitações dos números primitivos do JavaScript, eles servem a propósitos diferentes:

  • Decimal: Foca na precisão exata para números com casas decimais, resolvendo os problemas de ponto flutuante em operações que envolvem frações e cálculos monetários. Ele lida com a representação precisa de números que podem não ter uma representação binária finita exata.

  • BigInt: Introduzido na especificação ECMAScript 2020, o BigInt é um tipo numérico primitivo que pode representar inteiros arbitráriamente grandes, superando o limite do Number.MAX_SAFE_INTEGER. Ele é ideal para trabalhar com números inteiros que excedem a capacidade dos números de ponto flutuante padrão.

Vamos ilustrar com exemplos em TypeScript, demonstrando boas práticas:

// Exemplo de uso de uma biblioteca Decimal (simulada para fins educacionais)
// Em um cenário real, você usaria uma biblioteca como 'decimal.js' ou 'big.js'

/**
 * Representa um número decimal com precisão exata.
 * Em uma implementação real, isso seria uma classe que encapsula a lógica.
 */
class PreciseDecimal {
    private value: string; // Armazena o número como string para precisão

    constructor(num: number | string) {
        // Em uma implementação real, haveria validação e conversão robusta.
        this.value = String(num);
    }

    add(other: PreciseDecimal): PreciseDecimal {
        // Lógica complexa de adição decimal aqui.
        // Para este exemplo, apenas simulamos o resultado correto.
        const num1 = parseFloat(this.value);
        const num2 = parseFloat(other.value);
        // Note que esta simulação ainda usa parseFloat internamente para demonstração,
        // uma implementação real não faria isso para a operação principal.
        return new PreciseDecimal((num1 + num2).toFixed(10)); // toFixed para simular resultado preciso
    }

    // Outros métodos como subtract, multiply, divide, etc.

    toString(): string {
        return this.value;
    }
}

// Utilizando a classe simulada PreciseDecimal
const amount1 = new PreciseDecimal(0.1);
const amount2 = new PreciseDecimal(0.2);
const preciseSum = amount1.add(amount2);

console.log(`Soma decimal precisa: ${preciseSum.toString()}`); // Saída esperada: 0.3 (ou similar, dependendo da precisão configurada)

// Exemplo com BigInt
// Trabalhando com inteiros muito grandes
const veryLargeNumber1: bigint = BigInt(\"900719925474099100\"); // Excedendo MAX_SAFE_INTEGER
const veryLargeNumber2: bigint = BigInt(\"100");

const bigIntSum: bigint = veryLargeNumber1 + veryLargeNumber2;

console.log(`Soma BigInt: ${bigIntSum}`); // Saída: 900719925474099200
Enter fullscreen mode Exit fullscreen mode

Conclusão

A precisão é um pilar fundamental em muitas aplicações. Enquanto o JavaScript evolui, a necessidade de lidar com números decimais de forma precisa se torna cada vez mais premente. A proposta de um tipo Decimal na TC39 representa um passo significativo em direção a um ecossistema JavaScript mais robusto e confiável.

Compreender a diferença entre Decimal e BigInt é crucial para escolher a ferramenta certa para o trabalho: Decimal para precisão com casas decimais e BigInt para inteiros de grande magnitude. À medida que o padrão evolui, podemos esperar que o desenvolvimento de aplicações de alta precisão em JavaScript se torne mais direto e menos propenso a erros sutis.

Top comments (0)