dinerojs / dinero.js

Create, calculate, and format money in JavaScript and TypeScript.

Home Page:https://v2.dinerojs.com/docs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wrong value when divide using allocate

b-runo opened this issue · comments

aux_total = 1.000; //this value come in a properly Dinero object

aux_qtde_parcelas = 3;

aux_divisor = Math.round(10000 * (1 / aux_qtde_parcelas));
    
valor_parcela = allocate(aux_total, [aux_divisor, 10000 - aux_divisor])[0];

When i print the value of the var valor_parcela shows 333.30, but it should show 333.33.
What am i doing wrong?

The behaviour by Dinero here is correct, let's run through with values (I've split up some of the computation to make it a bit clearer):

// Let's just use USD for an example
aux_total = dinero({ amount: 100000, currency: USD }); // $1000 and zero cents

aux_qtde_parcelas = 3;

aux_divisor = Math.round(10000 * (1 / aux_qtde_parcelas)); // this value is 3333 (round(3333.33) = 3333)
    
ratios =  [aux_divisor, 10000 - aux_divisor]; // [3333, 6667]

valor_parcelas = allocate(aux_total, ratios); // [amount: 33330, amount: 66670]

valor_parcela = valor_parcelas[0]; // amount: 33330, or $333.30
other_valor = valor_parcelas[1]; // amount: 66670, or $666.70

If what you're trying to do is split a value into two chunks, one representing 1/3 of the initial value, and the other to be 2/3 of the initial value, you'll need to use allocate without rounding.

aux_total = dinero({ amount: 100000, currency: USD }); // $1000 and zero cents

valor_parcelas = allocate(aux_total, [1, 2]); // [amount: 33334, amount: 66666]
valor_parcela = valor_parcelas[0] // amount: 33334, or $333.34
other_valor = valor_parcelas[1] // amount: 66666, or $666.66

Note that the first value is still not $333.33 like you wanted - you will end up with remainder cents being distributed to each of the values - 100000 is not perfectly divisible by 3, you will get some remainder. Reading the Dinero source code, the remainder is allocated to the values left-to-right.

Thanks

I have found that setting the ratios to "bucket sizes" rather than decimal ratios or similar is more appropriate.
I.e. instead of 0.333 and 0.667 you could just do [1,2]. If you can do it this way it just removes a whole lot of precision problems.

Closing this as this appears to be solved. Feel free to reopen if necessary.