Banking Rounding for Decimal rounding off on Linux

Hi All,

After I investigated ccr below, I found an rounding issue. The issue is that we can get different result

between Linux and Windows platform when we do the decimal rounding with string format or print

function.

 

Please refer to the screenshots first.

 

Pic1 Windows program and result.

 

 

                    Pic1 Windows program and result.

 

Pic2 & Pic3 Linux program and result

 

 

               Pic2 Linux Program

 

 

                                                                Pic3  Linux Result

 

I use the same simple program on Linux and Windows to describe this situation.

On Windows, from Pic1, the variables  are

d3 =  37.114500000000000                                     d3 = 37.115

d4 =  37.113500000000002     result                    d4 = 37.114

d5 =  37.116500000000002                                     d5 = 37.117

 

On Linux , from Pic2, the variables are

 

d3 =  37.114500000000000                                     d3 = 37.114

d4 =  37.113500000000002     result                    d4 = 37.114

d5 =  37.116500000000002                                     d5 = 37.117

 

The apparent difference is the value of d3 in result. This is also the behavior of this CCR.

After searching Google, I find the reason is the different algorithm used in Linux and Windows when doing the decimal rounding.

On Windows, decimal rounding uses the common  rounding off. However, On Linux, it uses the banking rounding.

Decimal rounding takes different algorithm principle between GNU C library in Linux and CRT library in Windows.

 

Please refer to the explanation as below.

Common method (Windows C/C++ used)

This method is commonly used in mathematical applications, for example in accounting. It is the one generally taught in elementary mathematics classes. This method is also known as Asymmetric Arithmetic Rounding or Round-Half-Up (Asymmetric Implementation)

1. Divide it by the unit to which it is to be rounded

2. Round it to the nearest whole number, unless it ends in exactly .5

3. If it ends in exactly .5, then add 0.5

4. Multiply it by the unit to which it is to be rounded

Examples (rounded to hundredths):

  • 3.0448 → 304.48 → 304 → 3.04
  • 3.0450 → 304.50 → 305 → 3.05       matched (d3)
  • 3.0452 → 304.52 → 305 → 3.05       matched (d5)
  • -3.0448 → -304.48 → -304 → -3.04
  • -3.0450 → -304.50 → -304 → -3.04
  • -3.0452 → -304.52 → -305 → -3.05

As the name implies, this can introduce a bias: if all the unrounded numbers had four decimal places, say, then in our example the expected average of the rounded numbers will be 0.0005 higher than that of the unrounded numbers.

Round-to-even method (Linux C/C++ used)

This method, also known as unbiased roundingconvergent roundingstatistician's roundingDutch roundingGaussian rounding, or bankers' rounding, exactly replicates the common method of rounding except when the digit(s) following the rounding digit starts with a five and has no non-zero digits after it.

Despite the custom of rounding the number 4.5 up to 5, in fact 4.5 is no nearer to 5 than it is to 4 (it is 0.5 away from both). When dealing with large sets of scientific or statistical data, where trends are important, traditional rounding on average biases the data upwards slightly. Over a large set of data, or when many subsequent rounding operations are performed as in digital signal processing, the round-to-even rule tends to reduce the total rounding error, with (on average) an equal portion of numbers rounding up as rounding down. This generally reduces upwards skewing of the result.

The new algorithm becomes (only rule 3. changes):

1. Divide it by the unit to which it is to be rounded

2. Round it to the nearest whole number, unless it ends in exactly .5

3. If it ends in exactly .5, then round towards the nearest even whole number

4. Multiply it by the unit to which it is to be rounded

Examples (rounded to hundredths):

  • 3.0448 → 304.48 → 304 → 3.04
  • 3.0450 → 304.50 → 304 → 3.04         matched (d3)
  • 3.0452 → 304.52 → 305 → 3.05         matched (d5)
  • -3.0448 → -304.48 → -304 → -3.04
  • -3.0450 → -304.50 → -304 → -3.04
  • -3.0452 → -304.52 → -305 → -3.05

More details, please refer to

<1> http://www.cnblogs.com/samcn/archive/2009/06/05/1497094.html

<2> https://zh.wikipedia.org/wiki/%E6%95%B0%E5%80%BC%E4%BF%AE%E7%BA%A6

<3> https://en.wikipedia.org/wiki/Rounding#Round_half_to_even

There is switch for linux to decide which kind of rounding used when programming.

posted @ 2015-11-05 17:25  飞在风口的猪  阅读(304)  评论(0编辑  收藏  举报