Why does Python not solve the "bug" of rounding (round "?

Source: Internet
Author: User
Php Chinese network (www.php.cn) provides the most comprehensive basic tutorial on programming technology, introducing HTML, CSS, Javascript, Python, Java, Ruby, C, PHP, basic knowledge of MySQL and other programming languages. At the same time, this site also provides a large number of online instances, through which you can better learn programming... Reply content: This problem cannot be solved because of the binary floating point number.

Let's first look at a phenomenon that has nothing to do with round:

>>> Def show (x ):... "print a number, 20-bit precision """... print ('{:. 20f }'. format (x)... >>> show (1.5) 1.50000000000000000000 >>>> show (1.25) 1.25000000000000000000 >>>> show (1.245) 1.24500000000000010658 >>> show (1.45) 1.44999999999999995559 >>> show (1.415) 1.41500000000000003553
Rounding is based on decimal, and there is an error when the binary cannot be accurately expressed.
Any place that requires decimal operations must replace float with Decimal. decimal:

>>> Decimal(1.45)Decimal('1.4499999999999999555910790149937383830547332763671875')>>> Decimal('1.45')Decimal('1.45')>>> Context(prec=2, rounding=ROUND_HALF_UP).create_decimal('1.45')Decimal('1.5')>>> Decimal('1.45').normalize(Context(prec=2, rounding=ROUND_HALF_UP))Decimal('1.5')>>> Decimal(Decimal('1.45').quantize(Decimal('.1'), rounding=ROUND_HALF_UP))Decimal('1.5')
Note that this is in the very nature of binary floating-point: this is not a bug in Python, and it is not a bug in your code either. you'll see the same kind of thing in all ages that support your hardware's floating-point arithmetic (although some ages may not DisplayThe difference by default, or in all output modes ).
  • Some decimal numbers (such as 0.1) cannot be accurately expressed with a finite number of binary digits 0 and 1 in the machine. you can only increase the precision by adding a fixed number of digits, so as to be closer to the original decimal number.

Round ( Number[, Ndigits])
Return the floating point value NumberRounded NdigitsDigits after the decimal point. If NdigitsIs omitted, it defaults to zero. The result is a floating point number. Values are rounded to the closest multiple of 10 to the power minus Ndigits; If two multiples are equally close, rounding is done away from 0.
  • The round function of python is defined to take the value closest to the number in any integer * 10 ^ (-ndigits, if two integers are equal to the number, the value is determined by the side away from 0 (negative-0-positive.

round(0.5) is 1.0 and round(-0.5) is -1.0)
The subject test has nothing to do with the bug. Round is a four-house, six-in-five pair. There is indeed a problem with the official implementation of python. for the reasons why the author does not improve, the author may be confused. For more information, see Liu Haiyang's answer. The general mentality may be: this error is not with me, so although there is a way, I will not solve this problem.

At first glance, many people will regard this issue as an inaccurate floating point number. Float numbers are not accurate. this is common sense and correct.

However, floating point numbers are not accurate in all circumstances, nor are they 「 As long as the floating point number is not accurate, the related computing problems involved have no value to solve.」.

Python's round problem is a typical example. The author argues that this kind of problem related to floating point precision is not necessary to solve. Like @ Liu Haiyang's point of view, the result is now returned.

However, careful analysis will find that the floating point number 0.5 can be accurately expressed, and the specific feature of the round function is that the accuracy after round rounding is meaningless. Therefore, the inaccuracy caused by the round problem can be solved.

For the inaccuracy of round, it is important to determine whether the result is a forward or backward query. I wrote a simple example to illustrate this problem. of course, this function is not accurate under certain circumstances, but the correct results can be obtained when the question is given.

#include 
  
   float my_round(float src, int idx){    int i;    for (i=idx;i--;)        src *=10;    float dest = (int)src;    if (src >= dest+0.5)        dest += 1;    for (i=idx;i--;)        dest /=10;    return dest;}int main(){    printf("result=%f\n", my_round(1.5, 0));    printf("result=%f\n", my_round(1.25, 1));    printf("result=%f\n", my_round(1.245, 2));    printf("result=%f\n", my_round(1.45, 1));    printf("result=%f\n", my_round(1.415, 2));    printf("result=%f\n", my_round(2.675, 2));}
  
Two problems: one is
Real Storage of floating point numbers in computers (stored in Python)

expect:  1.0actual:  1expect:  1.1actual:  1.100000000000000088817841970012523233890533447265625expect:  1.2actual:  1.1999999999999999555910790149937383830547332763671875expect:  1.3actual:  1.3000000000000000444089209850062616169452667236328125expect:  1.4actual:  1.399999999999999911182158029987476766109466552734375expect:  1.5actual:  1.5expect:  1.6actual:  1.600000000000000088817841970012523233890533447265625expect:  1.7actual:  1.6999999999999999555910790149937383830547332763671875expect:  1.8actual:  1.8000000000000000444089209850062616169452667236328125expect:  1.9actual:  1.899999999999999911182158029987476766109466552734375
It is very simple, because 2.675 may be expressed as 2.6749, so after round is 2.67, your need is essentially: precise decimal operation. However, float is not designed to meet this requirement, but decimal is. Therefore, it is difficult to create a separate round for float, which does not meet the design intent of float. Taking your function as an example, the temp * 10 operation is not accurate under float.

>>> 1.222*10
12.219999999999999 I mean why don't I write a function that can solve this problem: for example (in just one example, performance may definitely not work. The official website does not write a similar one for any reason)
Def myround (par, l ):
Temp = 1
For I in range (l ):
Temp * = 10
V = int (par + 0.5/temp) * temp)/temp
Return v

I = 1.25.
Print (myround (I, 1 ))
I = 1.245.
Print (myround (I, 2 ))
I = 1.21.
Print (myround (I, 1 ))
I = 1.249.
Print (myround (I, 2 ))

----
1.3
1.25
1.2
1.25 his explanation should be said that this is not a bug. The default value is float, and float is not precise, so python should be precise only to decimal. I think this is quite normal.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.