473,796 Members | 2,625 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Weird result returned from adding floats depending on order I add them

I'm getting different results when I add up a list of floats depending
on the order that I list the floats. For example, the following returns
False:
def check():
totalProp=0
inputs=[0.2,0.2,0.2,0.1 ,0.2,0,0.1]
for each in inputs:

totalProp+=each
print "totalProp=",to talProp
if totalProp != 1:
print "Your proportions must add up to 1"

return False
return True

However, if I swap, the 4th and 5th list items like this:

totalProp=0
inputs=[0.2,0.2,0.2,0.2 ,0.1,0,0.1]
for each in inputs:

totalProp+=each
print "totalProp=",to talProp
if totalProp != 1:
print "Your proportions must add up to 1"

return False
return True

I get True returned. Can anyone tell me whats going on and how I can
avoid the problem. Thanks

Joanne Matthews
Feb 20 '07 #1
9 1552
joanne matthews (RRes-Roth) a écrit :
I'm getting different results when I add up a list of floats depending
on the order that I list the floats. For example, the following returns
False:
def check():
totalProp=0
inputs=[0.2,0.2,0.2,0.1 ,0.2,0,0.1]
for each in inputs:

totalProp+=each
print "totalProp=",to talProp
if totalProp != 1:
print "Your proportions must add up to 1"

return False
return True

However, if I swap, the 4th and 5th list items like this:

totalProp=0
inputs=[0.2,0.2,0.2,0.2 ,0.1,0,0.1]
for each in inputs:

totalProp+=each
print "totalProp=",to talProp
if totalProp != 1:
print "Your proportions must add up to 1"

return False
return True

I get True returned. Can anyone tell me whats going
Its related to the internal representation of real numbers using a
finite number of binary digits - intermediate additions may (here the
order is have an impact) produce results which have no representation,
and lead to dismiss of an epsilon value.

http://en.wikipedia.org/wiki/Floating_point
on and how I can
avoid the problem. Thanks
Use an ad-hoc library with numerical types using a different
representation (other posters may give examples of libraries they use).
Feb 20 '07 #2
Hi,
I'm getting different results when I add up a list of floats depending
on the order that I list the floats. For example, the following returns

[snip summation]

if totalProp != 1:
From a numerical analysis point of view, never ever do this. The values
you are adding are approximations to the numbers you require, you then
test for equality (the real no no)...

There is even a section in the Python tutorial about it:

http://docs.python.org/tut/node16.html

Cheers,
John McCallum
Edinburgh
Feb 20 '07 #3
On Feb 20, 11:29 pm, "joanne matthews (RRes-Roth)"
<joanne.matth.. .@bbsrc.ac.ukwr ote:
I'm getting different results when I add up a list of floats depending
on the order that I list the floats.
This is quite expected. Floating point arithmetic is subject to
rounding errors.

[doesn't add to 1.0]
inputs=[0.2,0.2,0.2,0.1 ,0.2,0,0.1]

However, if I swap, the 4th and 5th list items like this:

inputs=[0.2,0.2,0.2,0.2 ,0.1,0,0.1]
[adds to 1.0]

What is happening:

print repr(whatever_y ou_are_puzzled_ by) is a Very Good Idea (TM).
>>a = [0.2, 0.2, 0.2, 0.1, 0.2, 0.1]
b = [0.2, 0.2, 0.2, 0.2, 0.1, 0.1]
sum(a)
1.0000000000000 002
>>sum(b)
1.0
>>tot = 0.0
for x in a:
.... tot += x
.... print repr(x), repr(tot)
....
0.2000000000000 0001 0.2000000000000 0001
0.2000000000000 0001 0.4000000000000 0002
0.2000000000000 0001 0.6000000000000 0009
0.1000000000000 0001 0.7000000000000 0007
0.2000000000000 0001 0.9000000000000 0013
0.1000000000000 0001 1.0000000000000 002
>>tot = 0.0
for x in b:
.... tot += x
.... print repr(x), repr(tot)
....
0.2000000000000 0001 0.2000000000000 0001
0.2000000000000 0001 0.4000000000000 0002
0.2000000000000 0001 0.6000000000000 0009
0.2000000000000 0001 0.8000000000000 0004
0.1000000000000 0001 0.9000000000000 0002
0.1000000000000 0001 1.0
>>>
As you can see, 0.1 and 0.2 can't be represented exactly as floating
point numbers. Consequently there is only a rough chance that they
will add up to what you think they should add up to.

Fixes:

(1) Round the sums to a suitable precision.
>>round(sum(a ), 3)
1.0
>>round(sum(b ), 3)
1.0
>>>
(2) Test against a range, rather than for equality:
>>abs(sum(a) - 1.0) < 0.001
True
>>abs(sum(b) - 1.0) < 0.001
True
>>>
(3) Use the Decimal module

(4) Google this group (or the Python cookbok, I forget which) for
fancy algorithms for doing accurate sums of lists of floats.

HTH,
John

Feb 20 '07 #4
On 2007-02-20, joanne matthews (RRes-Roth) <jo************ *@bbsrc.ac.ukwr ote:
I'm getting different results when I add up a list of floats depending
on the order that I list the floats.
That's how floats work.
For example, the following returns
False:
def check():
totalProp=0
inputs=[0.2,0.2,0.2,0.1 ,0.2,0,0.1]
for each in inputs:

totalProp+=each
print "totalProp=",to talProp
if totalProp != 1:
Floating point operations are not exact. This test requires
them to be.

[...]
Can anyone tell me whats going on
IEEE floating point can not exactly represent 0.2 nor 0.1, so
you get approximations.
and how I can avoid the problem.
Don't use floating point if you expect exact results.

--
Grant Edwards grante Yow! I feel better about
at world problems now!
visi.com
Feb 20 '07 #5
On Feb 21, 2:05 am, Grant Edwards <gra...@visi.co mwrote:
On 2007-02-20, joanne matthews (RRes-Roth) <joanne.matth.. .@bbsrc.ac.ukwr ote:
I'm getting different results when I add up a list of floats depending
on the order that I list the floats.
>
Don't use floating point if you expect exact results.
It's not the floating point that's the problem, it's the radix, in
this case 2, not being able to express n/10 exactly. As the tutorial
points out, radix-10 has problems representing n/3 (and n/7 and ...)
exactly.

Another take: Don't expect exact results. If the input is exact to 1
or two decimal places, don't expect the sum to be exact to 15 or more
decimal places.

Feb 20 '07 #6
On 2007-02-20, John Machin <sj******@lexic on.netwrote:
On Feb 21, 2:05 am, Grant Edwards <gra...@visi.co mwrote:
>On 2007-02-20, joanne matthews (RRes-Roth) <joanne.matth.. .@bbsrc.ac.ukwr ote:
I'm getting different results when I add up a list of floats depending
on the order that I list the floats.
>>
Don't use floating point if you expect exact results.

It's not the floating point that's the problem, it's the radix, in
this case 2, not being able to express n/10 exactly. As the tutorial
points out, radix-10 has problems representing n/3 (and n/7 and ...)
exactly.
No matter what radix you choose, you're going to be able to
exactly represent 0% of the rational numbers within the range
of the representation. Since you have no control over the FP
representation (and hence radix), and little control over input
values, the only sane thing to do is to write your code under
the assumption that FP can't represent any values exactly.
Another take: Don't expect exact results.
Which is what I said. :)
If the input is exact to 1 or two decimal places, don't expect
the sum to be exact to 15 or more decimal places.
In this case the input values have about 14 significant digits.
So does the output. Unfortunately, the algorithm as written
requires an infinite number of significant digits.

--
Grant Edwards grante Yow! WHOA!! Ken and
at Barbie are having TOO
visi.com MUCH FUN!! It must be the
NEGATIVE IONS!!
Feb 20 '07 #7
On Feb 21, 3:44 am, Grant Edwards <gra...@visi.co mwrote:
On 2007-02-20, John Machin <sjmac...@lexic on.netwrote:
On Feb 21, 2:05 am, Grant Edwards <gra...@visi.co mwrote:
On 2007-02-20, joanne matthews (RRes-Roth) <joanne.matth.. .@bbsrc.ac.ukwr ote:
Don't use floating point if you expect exact results.

Another take: Don't expect exact results.

Which is what I said. :)
It may well be what you said. I didn't hear that. What you wrote was
"Don't use floating point if you expect exact results." That is *not*
the same as "Don't expect exact results".

Feb 20 '07 #8
On Feb 20, 6:08 am, "John Machin" <sjmac...@lexic on.netwrote:
>for x in b:

... tot += x
... print repr(x), repr(tot)
...
0.2000000000000 0001 0.2000000000000 0001
0.2000000000000 0001 0.4000000000000 0002
0.2000000000000 0001 0.6000000000000 0009
0.2000000000000 0001 0.8000000000000 0004
0.1000000000000 0001 0.9000000000000 0002
0.1000000000000 0001 1.0

As you can see, 0.1 and 0.2 can't be represented exactly as floating
point numbers. Consequently there is only a rough chance that they
will add up to what you think they should add up to.
Although your point is correct, this is actually a myth about repr.
The goal of repr is to be able to round-trip all numbers, so
eval(repr(n)) == n. From that perspective it would be perfectly legal
if it printed out a nice and short "0.2" or "0.1".

As for the actual value, although you can't express all non-repeating
base-10 values with non-repeating base-2, you can express base-2 with
base-10. It just gets a little long:
>>'%.60f' % 0.2
'0.200000000000 000011102230246 251565404236316 680908203125000 000'
>>'%.60f' % 0.1
'0.100000000000 000005551115123 125782702118158 340454101562500 000'

Unfortunately this method of printing out floats won't work for
smaller values, since the %f formatting limits the number of decimal
places.

But if you want a more compact exact representation I have bodged
together a way of printing out floats in base-16:
>>hexfloat(0. 2)
hexfloat('0.333 33333333334')
>>hexfloat(0. 1)
hexfloat('0.199 9999999999A')

Interesting, if a bit confusing.

Feb 21 '07 #9
Hello Joanne,
... [float problem] ...
I get True returned. Can anyone tell me whats going on and how I can
avoid the problem. Thanks
If you want to be truly accurate, you can use gmpy.mpq (http://
gmpy.sourceforg e.net/).
>>a = [0.2, 0.2, 0.2, 0.1, 0.2, 0.1]
b = [0.2, 0.2, 0.2, 0.2, 0.1, 0.1]
qa = [gmpy.mpq(int(i * 10), 10) for i in a]
qb = [gmpy.mpq(int(i * 10), 10) for i in b]
sum(qa)
mpq(1)
>>sum(qb)
mpq(1)
>>sum(qa) == sum(qb)
True

HTH,
--
Miki <mi*********@gm ail.com>
http://pythonwise.blogspot.com

Feb 21 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2081
by: redneck_kiwi | last post by:
Hi all: I have a really weird problem. I am developing a customer catalog system for my company and as such have delved into sessions for authentication and access levels. So far, I have managed to get a working system just about finished. I am building an interface for our customer service folks to use to manage registered customers and am seeing some weird behavior.
10
4030
by: Charles Law | last post by:
For some reason, when I click the X to close my MDI parent form, the action appears to be re-directed to one of the MDI child forms, and the parent remains open. I am then unable to close the application. What should happen, is that the main MDI form should close, taking the child forms with it. There is code to loop through the child forms, remove the controls on each of them, and then close the form, but this code should execute only...
3
2269
by: lagj | last post by:
Using MySQL 5.0.15 I am no expert so maybe I am deeply misundertanding how this should work. I have a relatively complex quey with joins and a subquery (it is probably far from optimized, but that is another issue; right now I am more interested in correctness than speed). If I do not put a GROUP BY clause then the query returns a number of rows, as expected. If I add a GROUP BY clause, I get an empty set! My understanding of the...
38
2793
by: baong | last post by:
dear all i have use this line to time in many my web base appl. but now i found a weird problem the javascript line is the same but i use the calculation 2 time @ the first time, it is ok, 3 * 31.9 = 95.7 @ the second time, 3 * 31.9 = 95.69999999999999 this is the list number which calculation is NOT correct 6 * 31.9 = 191.39999999999998 7
5
1306
by: kelmen | last post by:
Try the below simple program. It give expected result. 1 1 2 2 Then toggle the statements in private static int sinc(), to use Test._num ++ .
12
2409
by: syn1kk | last post by:
1: float (*data); 2: data = malloc(31 * sizeof(data)); 3: data = VARIABLE; Question 1: The variable data is a float pointer? Question 2: When the is used. Does that mean it is an array of float pointers? What does it mean? Question 3: Or does it mean that there are 16384 floats allocated with
9
2701
by: serge | last post by:
/* Subject: How to build a procedure that returns different numbers of columns as a result based on a parameter. You can copy/paste this whole post in SQL Query Analyzer or Management Studio and run it once you've made sure there is no harmful code. Currently we have several stored procedures which final result is a select with several joins that returns many
18
1997
by: atv | last post by:
at least to me it is. I can't figure out for the life what it is i'm doing wrong here. i have a function called assign_coordinate. usually, i pass a malloced pointer to it, then individual pointers are malloced within that function. No problem here. Now i have a situation in this software, where i need to assign new coordinates to all nodes in the list.
135
4330
by: robinsiebler | last post by:
I've never had any call to use floating point numbers and now that I want to, I can't! *** Python 2.5.1 (r251:54863, May 1 2007, 17:47:05) on win32. *** 0.29999999999999999 0.29999999999999999
0
10237
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10018
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9055
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7553
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6795
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5446
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5578
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4120
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2928
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.