Float Rounding

Some data about Float ROunding

This section in the python tutorial can be interesting.

Bruce M. Bush's from Lahey article is covering many aspects of float rounding.

A TechnicalNoteOnRoundingInAccounting page is in progress.

Problem¶

* Problem 1: ratios applied to amounts must be rounded for accounting. (ex. 19.6% of 0.10 EUR = 0.02 EUR)

* Problem 2: 0.22 + 0.11 + 0.11 = 0.44 and not 0.43999999999999

* Problem 3: round(a) + round(b) is not round(a + b)

* Problem 4: total_price must be rounded if currency

* Problem 5: 100000000000000000000000000000001 = 100000000000000000000000000000000 with floats

Solution¶

* Solution 1: use currency object to round for given currency (in applied rules, in scripts, in total price) ie. wherever the amount uses a currency. The result is a python decimal object. Ex. getTotalPrice returns a decimal object.

* Solution 1b: use 64 bit integers (in cents, in millims)

* Solution 2: add a decimal_quantity to MySQL stock table. Make total_price a decimal in MySQL. If necessary,only index decimal_quantity for certain portal types. A simple float rounding problem can be seen with this python code:

>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1
0.99999999999999989
>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 == 1
False

* Solution 3: extend getInventory API to produce all types of balances and histories with decimals

* Solution 4a: add a decimal type to propertysheet and use my_decimal_quantity in forms

* Solution 4b: add a decimal widget and replace float widget with decimal widget for certain my_quantity

* Another idea: Use longs, multiply them by 1/resource_precision.

precision = 1/resource_precision
total_price = sum(total_price * precision) / precision

More Solution¶ (Problem 2)¶

* SELECT SUM(BIGINT(quantity * 100)) / 100

• should be quite fast and sufficient in most cases

More Solution¶ (Problem 2 and part of Problem 5)¶

* SELECT SUM(DECIMAL(quantity, 30))

• should be really precise

More Solution¶ (Problem 1)¶

* Include rounding in any value related to accounting (ex. total price in invoice or proforma)

• (ex. VAT value, salary values)

More Solution¶ (Problem 3)¶

* Add a line to accounting to store the difference in a special account

• round(a) + round(b) - round(a + b)

More Solution¶

* Implement arithmetics on amounts directly. (on the class)

Another problem: delivery_error in the simulation¶

delivery_error is a property on simulation movements for rounding problems:

simulation.quantity + simulation.delivery_error = simulation.delivery_ratio * delivery.quantity

A solver which solve quantity divergence is able and must update the error value for the quantity divergence it solves.

IMHO in solver one shall/may set delivery_error as:

simulation_movement.edit(delivery_error = simulation_movement.getDeliveryRatio() * quantity_collected_on_input -
simulation_movement.getCorrectedQuantity())