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.