From fab58ab892b6a016376fb5a636c1b0a9abd81901 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 19 Oct 2020 01:40:27 +1100 Subject: [PATCH] Fix rounding errors in unweighted inclusive Gregory mode --- pyRCV2/method/base_stv.py | 4 ++-- pyRCV2/numbers/fixed_js.py | 5 +++++ pyRCV2/numbers/fixed_py.py | 5 +++++ pyRCV2/numbers/int_js.py | 5 +++++ pyRCV2/numbers/int_py.py | 5 +++++ pyRCV2/numbers/native_js.py | 5 +++++ pyRCV2/numbers/native_py.py | 5 +++++ pyRCV2/numbers/rational_js.py | 3 +++ pyRCV2/numbers/rational_py.py | 3 +++ 9 files changed, 38 insertions(+), 2 deletions(-) diff --git a/pyRCV2/method/base_stv.py b/pyRCV2/method/base_stv.py index ecb066d..6b9fcc7 100644 --- a/pyRCV2/method/base_stv.py +++ b/pyRCV2/method/base_stv.py @@ -416,7 +416,7 @@ class BaseUIGSTVCounter(BaseSTVCounter): for ballot in cand_ballots: __pragma__('opov') - new_value = (Rational(ballot.value.pp(0)) * Rational(surplus.pp(0))) / Rational(total_ballots.pp(0)) + new_value = (ballot.value.to_rational() * surplus.to_rational()) / total_ballots.to_rational() self.candidates[candidate].ballots.append((ballot, new_value)) __pragma__('noopov') @@ -428,7 +428,7 @@ class BaseUIGSTVCounter(BaseSTVCounter): for ballot in next_exhausted: __pragma__('opov') - new_value = (Rational(ballot.value.pp(0)) * Rational(surplus.pp(0))) / Rational(total_ballots.pp(0)) + new_value = (ballot.value.to_rational() * surplus.to_rational()) / total_ballots.to_rational() __pragma__('noopov') self.exhausted.ballots.append((ballot, new_value)) diff --git a/pyRCV2/numbers/fixed_js.py b/pyRCV2/numbers/fixed_js.py index 6485797..deec595 100644 --- a/pyRCV2/numbers/fixed_js.py +++ b/pyRCV2/numbers/fixed_js.py @@ -31,6 +31,11 @@ class Fixed: """Pretty print to specified number of decimal places""" return self.impl.toFixed(dp) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl.toString()) + def __add__(self, other): return Fixed(self.impl.plus(other.impl)) def __sub__(self, other): diff --git a/pyRCV2/numbers/fixed_py.py b/pyRCV2/numbers/fixed_py.py index 7a595d5..27b4e10 100644 --- a/pyRCV2/numbers/fixed_py.py +++ b/pyRCV2/numbers/fixed_py.py @@ -35,6 +35,11 @@ class Fixed: """Pretty print to specified number of decimal places""" return format(self.impl, '.{}f'.format(dp)) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl) + def __add__(self, other): return Fixed(self.impl + other.impl) def __sub__(self, other): diff --git a/pyRCV2/numbers/int_js.py b/pyRCV2/numbers/int_js.py index 928dae3..2571ae2 100644 --- a/pyRCV2/numbers/int_js.py +++ b/pyRCV2/numbers/int_js.py @@ -26,6 +26,11 @@ class NativeInt: """Pretty print to specified number of decimal places""" return self.impl.toFixed(0) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl) + def __add__(self, other): return NativeInt(self.impl + other.impl) def __sub__(self, other): diff --git a/pyRCV2/numbers/int_py.py b/pyRCV2/numbers/int_py.py index 41c7b34..ddd47c0 100644 --- a/pyRCV2/numbers/int_py.py +++ b/pyRCV2/numbers/int_py.py @@ -28,6 +28,11 @@ class NativeInt: """Pretty print to specified number of decimal places""" return str(self.impl) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl) + def __add__(self, other): return NativeInt(self.impl + other.impl) def __sub__(self, other): diff --git a/pyRCV2/numbers/native_js.py b/pyRCV2/numbers/native_js.py index b23afef..48489b5 100644 --- a/pyRCV2/numbers/native_js.py +++ b/pyRCV2/numbers/native_js.py @@ -26,6 +26,11 @@ class Native: """Pretty print to specified number of decimal places""" return self.impl.toFixed(dp) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl) + def __add__(self, other): return Native(self.impl + other.impl) def __sub__(self, other): diff --git a/pyRCV2/numbers/native_py.py b/pyRCV2/numbers/native_py.py index 702e9bf..21ac3fd 100644 --- a/pyRCV2/numbers/native_py.py +++ b/pyRCV2/numbers/native_py.py @@ -28,6 +28,11 @@ class Native: """Pretty print to specified number of decimal places""" return format(self.impl, '.{}f'.format(dp)) + def to_rational(self): + """Convert to an instance of Rational""" + from pyRCV2.numbers import Rational + return Rational(self.impl) + def __add__(self, other): return Native(self.impl + other.impl) def __sub__(self, other): diff --git a/pyRCV2/numbers/rational_js.py b/pyRCV2/numbers/rational_js.py index cacb27a..10cc9b2 100644 --- a/pyRCV2/numbers/rational_js.py +++ b/pyRCV2/numbers/rational_js.py @@ -29,6 +29,9 @@ class Rational: """ return self.impl.valueOf().toFixed(dp) + def to_rational(self): + return self + def to_num(self): """ Convert to an instance of Num diff --git a/pyRCV2/numbers/rational_py.py b/pyRCV2/numbers/rational_py.py index 9f23c81..1e090e0 100644 --- a/pyRCV2/numbers/rational_py.py +++ b/pyRCV2/numbers/rational_py.py @@ -31,6 +31,9 @@ class Rational: """ return format(self.impl, '.{}f'.format(dp)) + def to_rational(self): + return self + def to_num(self): """ Convert to an instance of Num