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!"

asked 22 Feb '12, 15:25

MrSparc's gravatar image

MrSparc
7296818

accept rate: 28%

retagged 28 Feb '12, 09:28

Margarita%20Manterola's gravatar image

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)

Margarita Ma...

Margarita%20Manterola's gravatar image

7 Answers:

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.

More info in the python page about floating points.

link

answered 22 Feb '12, 15:37

Margarita%20Manterola's gravatar image

Margarita Ma...
3.7k41948

Excellent answer marga, thank you!

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)

AndyAtUdacity ♦♦

AndyAtUdacity's gravatar image

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.

link

answered 22 Feb '12, 16:15

xyzzy-2's gravatar image

xyzzy-2
1.8k21137

edited 22 Feb '12, 16:17

Thank you marga by your explanation and link.

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’ "

Thank you for the answers!

link

answered 22 Feb '12, 16:38

MrSparc's gravatar image

MrSparc
7296818

edited 22 Feb '12, 16:41

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

link

answered 28 Feb '12, 19:45

Eduardo%20Bellani's gravatar image

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.

link

answered 22 Feb '12, 17:01

AndyAtUdacity's gravatar image

AndyAtUdacity ♦♦
57.6k112260301

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.

link

answered 24 Feb '12, 09:30

M_J_Colwell's gravatar image

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.

link

answered 26 Feb '12, 17:37

Chris%20Greene's gravatar image

Chris Greene
8718

edited 27 Feb '12, 11:23

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

(26 Feb '12, 19:54)

Nick Darling...

Nick%20Darlington-1's gravatar image
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)

Ftynse-2

Ftynse-2's gravatar image
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)

Chris Greene

Chris%20Greene's gravatar image
Your answer
Question text:

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • 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

Tags

×7,476
×2,215
×103
×88
×22

Asked: 22 Feb '12, 15:25

Seen: 1,297 times

Last updated: 28 Feb '12, 19:45