Hyper Open Edge Cloud

Float Rounding

Some data about Float Rounding.
  • Last Update:2016-05-16
  • Version:001
  • Language:en

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))

  • 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())

Related Articles