Fixed rounding bug in interpreter for negative values

This commit is contained in:
Denis Merigoux 2022-05-06 15:28:09 +02:00
parent e66df01492
commit 07198e326d
No known key found for this signature in database
GPG Key ID: EE99DCFA365C3EE3
2 changed files with 9 additions and 3 deletions

View File

@ -233,12 +233,16 @@ let handle_default_opt
let no_input : unit -> 'a = fun _ -> raise EmptyError
let ( *$ ) (i1 : money) (i2 : decimal) : money =
let rat_result = Q.mul (Q.of_bigint i1) i2 in
let i1_abs = Z.abs i1 in
let i2_abs = Q.abs i2 in
let sign_int = Z.sign i1 * Q.sign i2 in
let rat_result = Q.mul (Q.of_bigint i1_abs) i2_abs in
let res, remainder = Z.div_rem (Q.num rat_result) (Q.den rat_result) in
(* we perform nearest rounding when multiplying an amount of money by a
decimal !*)
if Z.(of_int 2 * remainder >= Q.den rat_result) then Z.add res (Z.of_int 1)
else res
if Z.(of_int 2 * remainder >= Q.den rat_result) then
Z.(add res (of_int 1) * of_int sign_int)
else Z.(res * of_int sign_int)
let ( /$ ) (m1 : money) (m2 : money) : decimal =
if Z.zero = m2 then raise Division_by_zero

View File

@ -138,6 +138,8 @@ class Money:
def __mul__(self, other: Decimal) -> 'Money':
cents = self.value.value
coeff = other.value
# TODO: change, does not work with negative values. Must divide the
# absolute values and then multiply by the resulting sign.
rat_result = self.value.value * other.value
out = Money(Integer(rat_result))
res, remainder = t_divmod(rat_result.numerator, rat_result.denominator)