Some data about Float ROunding
Table of Contents
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))
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())
Related Articles¶