FAQ
I have trouble with the code beneath to make an array with equally
spaced values
When I enter 100e-6 as start value, 700e-6 as end value and 100e-6 I
get the following result:
[ 0.0001 0.00022 0.00034 0.00046 0.00058 0.0007 ]
But I was hoping for:
[ 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007]
It works correctly for other values like 1,7,1 but not for 0.1,0.7,0.1
then again for 0.01,0.07,0.01

What I find strange is that for the 1st example "1+abs(float(endvalue)-
float(startvalue))/float(incr)" gives 7.0 but int() of this value
gives 6
can someone provide help with this issue?
thanks
jean

#!/usr/bin/python
import math
import numpy as np
print "Enter start value as a float (e.g. 0.001) or in scientific
notation (e.g. 1e-3): ",
startvalue = raw_input()
print "Enter end value: ",
endvalue = raw_input()
print "Enter step: ",
incr = raw_input()
#nom = number of measurements
nom=int(1+abs(float(endvalue)-float(startvalue))/float(incr))
array=np.linspace(float(startvalue), float(endvalue), float(nom))
print "Array with current values: ",array

## Search Discussions

• at Dec 18, 2012 at 1:09 pm ⇧ Jean Dubois wrote:

I have trouble with the code beneath to make an array with equally
spaced values
When I enter 100e-6 as start value, 700e-6 as end value and 100e-6 I
get the following result:
[ 0.0001 0.00022 0.00034 0.00046 0.00058 0.0007 ]
But I was hoping for:
[ 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007]
It works correctly for other values like 1,7,1 but not for 0.1,0.7,0.1
then again for 0.01,0.07,0.01

What I find strange is that for the 1st example "1+abs(float(endvalue)-
float(startvalue))/float(incr)" gives 7.0 but int() of this value
gives 6
can someone provide help with this issue?
thanks
jean

#!/usr/bin/python
import math
import numpy as np
print "Enter start value as a float (e.g. 0.001) or in scientific
notation (e.g. 1e-3): ",
startvalue = raw_input()
print "Enter end value: ",
endvalue = raw_input()
print "Enter step: ",
incr = raw_input()
#nom = number of measurements
nom=int(1+abs(float(endvalue)-float(startvalue))/float(incr))
array=np.linspace(float(startvalue), float(endvalue), float(nom))
print "Array with current values: ",array

If you repeat the calculation of the number of intervals in the interpreter
you get

1 + abs(0.0007-0.0001)/0.0001
6.999999999999999

Many numbers cannot be represented exactly as float (that's the price you
have to pay for covering a wide range with just a few (8) bytes), and you
have introduced such a small error. The subsequent int() call will round
that float to the integer below it:

int(_)
6

While applying round() would work here

int(round(1 + abs(0.0007-0.0001)/0.0001))
7

there is no once-and-for-all solution to the underlying problem. E. g.

x = 2.**53
x == x + 1
True
• at Dec 18, 2012 at 1:10 pm ⇧ Am 18.12.2012 13:37, schrieb Jean Dubois:
I have trouble with the code beneath to make an array with equally
spaced values
When I enter 100e-6 as start value, 700e-6 as end value and 100e-6 I
get the following result:
[ 0.0001 0.00022 0.00034 0.00046 0.00058 0.0007 ]
But I was hoping for:
[ 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007]
It works correctly for other values like 1,7,1 but not for 0.1,0.7,0.1
then again for 0.01,0.07,0.01

What I find strange is that for the 1st example "1+abs(float(endvalue)-
float(startvalue))/float(incr)" gives 7.0 but int() of this value
gives 6
can someone provide help with this issue?
thanks
jean

#!/usr/bin/python
import math
import numpy as np
print "Enter start value as a float (e.g. 0.001) or in scientific
notation (e.g. 1e-3): ",
startvalue = raw_input()
print "Enter end value: ",
endvalue = raw_input()
print "Enter step: ",
incr = raw_input()
#nom = number of measurements
nom=int(1+abs(float(endvalue)-float(startvalue))/float(incr))
array=np.linspace(float(startvalue), float(endvalue), float(nom))
print "Array with current values: ",array

The Problem is the accuracy/precision of floating point operations

Python 2.7.3 (default, Aug 1 2012, 05:14:39)
[GCC 4.6.3] on linux2
a = 100e-6 #start
b = 700e-6 #end
c = 100e-6 #incr
1+(b-a)/c
6.999999999999999

and the fact that int() only takes the integer part of a floating point
number.

int(1+(b-a)/c)
6

So you have to make a more detailed decision about the number of points
in the case that (end-start)/incr is not exactly an integer which it
will almost never be.

The np.arange(a,b,c) function chooses a simple rule: give a list of
numbers a + k * c with k running from 0 to the highest integer with a +
k * c < b.

np.arange(a,b,c)
array([ 0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006])

You can get your desired list by adding some epsilon to the value of b.
Just make sure your epsilon is quite small compared to c.

np.arange(a,b+1e-15,c)
array([ 0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007])

Greetings
• at Dec 18, 2012 at 1:37 pm ⇧ On 18 dec, 14:09, Peter Otten wrote:
Jean Dubois wrote:
I have trouble with the code beneath to make an array with equally
spaced values
When I enter 100e-6 as start value, 700e-6 as end value and 100e-6 I
get the following result:
[ 0.0001 ? 0.00022 ?0.00034 ?0.00046 ?0.00058 ?0.0007 ]
But I was hoping for:
[ 0.0001 ? 0.0002 ?0.0003 ?0.0004 ?0.0005 ?0.0006 0.0007]
It works correctly for other values like 1,7,1 but not for 0.1,0.7,0.1
then again for 0.01,0.07,0.01
What I find strange is that for the 1st example "1+abs(float(endvalue)-
float(startvalue))/float(incr)" gives 7.0 but int() of this value
gives 6
can someone provide help with this issue?
thanks
jean
#!/usr/bin/python
import math
import numpy as np
print "Enter start value as a float (e.g. 0.001) or in scientific
notation (e.g. 1e-3): ",
startvalue = raw_input()
print "Enter end value: ",
endvalue = raw_input()
print "Enter step: ",
incr = raw_input()
#nom = number of measurements
nom=int(1+abs(float(endvalue)-float(startvalue))/float(incr))
array=np.linspace(float(startvalue), float(endvalue), float(nom))
print "Array with current values: ",array
If you repeat the calculation of the number of intervals in the interpreter
you get
1 + abs(0.0007-0.0001)/0.0001
6.999999999999999

Many numbers cannot be represented exactly as float (that's the price you
have to pay for covering a wide range with just a few (8) bytes), and you
have introduced such a small error. The subsequent int() call will round
that float to the integer below it:
int(_)
6

While applying round() would work here
int(round(1 + abs(0.0007-0.0001)/0.0001))
7

there is no once-and-for-all solution to the underlying problem. E. g.
x = 2.**53
x == x + 1
True

thanks

jean
• at Dec 18, 2012 at 3:37 pm ⇧ On 12/18/2012 07:37 AM, Jean Dubois wrote:
I have trouble with the code beneath to make an array with equally
spaced values
When I enter 100e-6 as start value, 700e-6 as end value and 100e-6 I
get the following result:
[ 0.0001 0.00022 0.00034 0.00046 0.00058 0.0007 ]
But I was hoping for:
[ 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007]
It works correctly for other values like 1,7,1 but not for 0.1,0.7,0.1
then again for 0.01,0.07,0.01
I started this answer before there were any others visible, but had to
rush off to the dentist. Now I'm finishing it and sending it, even
though there's some overlap with the other posts.

What Python has in common with nearly every other language is the use of
binary floating point. Unlike integers, floating point values can have
both roundoff and quantization errors. The former happen with many
operations, like you can see with pencil and paper trying to divide 1 by
3, and storing the result in 10 columns.

But quantization errors aren't as obvious. They can occur whenever you
convert a number from one format to another. In this case, you're
converting from the decimal string to a binary float. To put it simply
binary floats can't store any decimal number exactly exact integers, and
mixed numbers where the fractional part happens to be an exact multiple
of a power of two. So 0.5 is exact, but you get quantization error with
0.1, 0.2, ... 0.9

This is compounded by the fact that print will convert the number back
to a decimal string. So sometimes the two quantization errors happen to
cancel, and sometimes they don't.

Now, your particular case is due to the convoluted way you calculate
nom. And the easiest way to fix it would be to add 0.5 before
truncating with int(). Or better yet, have the user tell you how many
he wants in his list, and calculate the other way around. If instead of
10 items, you have 100000 of them, you'll get a cumulative error with
your approach. So you'd use a formula like
start + (end-start)*i/nom

which would assure that each value was really close without cumulative
errors. No idea how that'd fit with numpy.

Another approach is to use the Decimal package. It's not inherently any
more accurate, but the errors are where you'd expect them, and you don't
get the quantization error converting back and forth to string.

--

DaveA

## Related Discussions

 view thread | post
Discussion Overview
 group python-list categories python posted Dec 18, '12 at 12:37p active Dec 18, '12 at 3:37p posts 5 users 4 website python.org

### 4 users in discussion

Content

People

Support

Translate

site design / logo © 2022 Grokbase