## Uniform distribution Quiz - Rounding errors with decimal values in web python interpreter?

I 've the following code:


n = 5
p = [1.0/n for i in range(n)]
print p


If I run with Python 2.7.1 + (on my linux box) I have the correct result (1/5 in each cell):

[0.2, 0.2, 0.2, 0.2, 0.2]


But if I run through the web interpret, I've as result:

[0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 0.20000000000000001]



 However, the submit seems that validation is done correctly and I get "You got it right!"

MrSparc
7296818

accept rate: 28%

Margarita Ma...
3.7k41948

Hi! If you liked the answer, please mark it as valid so that it doesn't show up as unanswered, thank you!

(28 Feb '12, 09:29)

This is due to the floating point representation. Because digital floating points are binary, it's quite hard to represent certain floating point numbers with the precision we would like them to be represented.

It may be that your interpreter is truncating the display so that it looks nicer to the eye. Internally it's always going to hold this very small "error", because it's intrinsic to the representation used in the computer.

Margarita Ma...
3.7k41948

For questions like this, we always have a window of acceptance. For this particular question, anything between 0.19999 and 0.20001 (I think) would have been accepted as correct.

(22 Feb '12, 15:50)

This is actually a really great teaching moment as floating point unreliability extends beyond just python. For example, the number .1 seems like an awful easy number to represent, right? It's just one tenth. Unfortunately, the computer doesn't work in base 10, but base 2, and in base 2, .1 is an irrational number (a number that repeats on and on for infinity, like 1/3 is .33333333333).

This actually ties back swimmingly to our discussion of the posterior distribution. Every time we work with floating point, we slightly reduce our confidence. For example, if we write the code

foo=1.0
foo=foo/10
foo=foo*10


then foo is actually just a hair off from 1.0. Python's pretty smart and can figure out that rounding error in most cases, but if it didn't automatically correct for us and we kept running the last 2 lines over and over again, we'd slowly be less and less able to say we were confidently at 1.0, but could only say we were close to it.

Now think about that in the context of the robot moving from the imprecise movement lesson. Every time the robot moves, it's fairly confident it knows where it moved, but it could be a little to the left or a little to the right. The more it moves, the less confident it's actually where it expects.

If you want to delve deeper into the topic, there's an MSDN article talking about the imprecision of floating point Here. I know this is a little deeper than the question you asked, but it's really interesting, especially the way it ties back so perfectly with the class, so I thought I'd share that neat little tidbit.

xyzzy-2
1.8k21137

I admit that I 've many years of experience in languages ​​like C, C + +, Java and PL / SQL and had never seen an error in floating-point values that have an exact division (like this: 1.0/5 = 0.2) in such languages.

I hope that the inf.system in my bank do not have been programmed in Python :) (Is just a joke).

But I also admit that I'm a python newbie :)

Anyway, in your related link explain why I've in Python 2.7.1 a different result:

"In versions prior to Python 2.7 and Python 3.1, Python rounded this value to 17 significant digits, giving ‘0.10000000000000001’. In current versions, Python displays a value based on the shortest decimal fraction that rounds correctly back to the true binary value, resulting simply in ‘0.1’ "

MrSparc
7296818

If anyone wishes to read into this a bit deeper, I highly recommend this paper:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

Eduardo Bellani
154412

For an excellent discussion about floating point numbers and these weird rounding errors, check out this lecture from MIT's introductory programming class. Start at 5:40 to get to the relevant part.

AndyAtUdacity ♦♦
58.2k112263304

Thanks for asking this question many students may be wondering why this occurs, well worth reading. Maybe add a link back to this question from Course web page? I bet It will get used. Consider adding links for 10 most popular answers.

M_J_Colwell
11

MrSparc,

I just checked g++. (SEE EDIT BELOW, this code originally compared 1/5==2 rather than .2 :( )

int main()
{
//volatile is used to try and prevent optimizations. Let me know if this doesn't actually work
//but the assembler seems to indicate the code does the right thing.
volatile double a = 1.0;
volatile double b = 5.0;
volatile double c = 0.2;
if(a/b == c){
printf("Python is weird\n");
}else{
printf("Floating point is weird\n");
}
}


The first

EDIT: The above code was completely wrong because I dyslexically swapped 0.2 with 2.0. The first is given ("Python is weird"), but as a commenter below pointed out, there are potentially optimization issues going on here. I'm going to check the assembler to see what's going on.

Chris Greene
8718

@ChrisG That's a relief, I'd actually be worried if it printed the first string ;)

(26 Feb '12, 19:54)

1

1/5.0 is actually 0.2 in math
so even if the floating point arithmetic in python or c++ were exact, your condition would fail

furthermore, g++ might produce different optimization for this code up to evaluating the condition at compile time and throwing out unnecessary code.

(27 Feb '12, 10:10)

1

@ftynse I changed things to use 1) the correct value and 2) volatile variables to prevent optimization. "Python is Weird is the Result". Let me know if I made any more boneheaded mistakes.

(27 Feb '12, 11:16)

Question text:

Markdown Basics

• *italic* or _italic_
• **bold** or __bold__
• image?![alt text](/path/img.jpg "Title")
• numbered list: 1. Foo 2. Bar
• to add a line break simply add two spaces to where you would like the new line to be.
• basic HTML tags are also supported

×7,521
×2,226
×103
×88
×22