diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py index 5cefcfba53..16fcb39921 100644 --- a/bindings/python/gnucash_core.py +++ b/bindings/python/gnucash_core.py @@ -648,7 +648,7 @@ class GncNumeric(GnuCashCoreClass): return a.div(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND) def _floordiv(a, b): - return a.div(b, 1, GNC_HOW_RND_TRUNC) + return a.div(b, 1, GNC_HOW_RND_FLOOR) __add__, __radd__ = _operator_fallbacks(_add, operator.add) __iadd__ = __add__ @@ -722,7 +722,7 @@ class GncNumeric(GnuCashCoreClass): return self.to_double() def __int__(self): - return int(self.to_double()) + return int(self.to_fraction()) def __pos__(a): """+a""" @@ -738,6 +738,9 @@ class GncNumeric(GnuCashCoreClass): def to_fraction(self): from fractions import Fraction + # A negative denominator multiplies: 3/-100 is 300. + if self.denom() < 0: + return Fraction(self.num() * -self.denom()) return Fraction(self.num(), self.denom()) def __str__(self): diff --git a/bindings/python/tests/test_numeric.py b/bindings/python/tests/test_numeric.py index 01293fe039..c91a9f5506 100644 --- a/bindings/python/tests/test_numeric.py +++ b/bindings/python/tests/test_numeric.py @@ -95,6 +95,28 @@ class TestGncNumeric(TestCase): self.assertEqual(10 + GncNumeric(3), GncNumeric(13)) self.assertEqual(10 * GncNumeric(3), GncNumeric(30)) + def test_to_int(self): + # int() truncates towards zero and must not round through a float. + self.assertEqual(int(GncNumeric(7, 2)), 3) + self.assertEqual(int(GncNumeric(-7, 2)), -3) + self.assertEqual(int(GncNumeric(2**53 + 1)), 2**53 + 1) + self.assertEqual(int(GncNumeric(-(2**62 + 1), 1)), -(2**62 + 1)) + self.assertEqual(int(GncNumeric(3, -100)), 300) + self.assertEqual(int(GncNumeric(-3, -100)), -300) + + def test_floordiv(self): + # // rounds towards negative infinity, as it does for int and Fraction. + self.assertEqual(GncNumeric(7, 2) // 1, GncNumeric(3)) + self.assertEqual(GncNumeric(-7, 2) // 1, GncNumeric(-4)) + self.assertEqual(GncNumeric(-1, 2) // 1, GncNumeric(-1)) + self.assertEqual(GncNumeric(-7) // GncNumeric(2), GncNumeric(-4)) + self.assertEqual(-7 // GncNumeric(2), GncNumeric(-4)) + self.assertEqual(GncNumeric(-6) // 3, GncNumeric(-2)) + self.assertEqual(GncNumeric(7) // -2, GncNumeric(-4)) + self.assertEqual(GncNumeric(-7) // GncNumeric(-2), GncNumeric(3)) + self.assertEqual(GncNumeric(7) // GncNumeric(3, 2), GncNumeric(4)) + self.assertEqual(GncNumeric(-7) // GncNumeric(3, 2), GncNumeric(-5)) + def test_incorect_args(self): with self.assertRaises(TypeError): GncNumeric(1, 2, 3)