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

  • Peter Otten 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
  • Alexander Blinne 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
    Type "help", "copyright", "credits" or "license" for more information.
    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
  • Jean Dubois 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
  • Dave Angel 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

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedDec 18, '12 at 12:37p
activeDec 18, '12 at 3:37p
posts5
users4
websitepython.org

People

Translate

site design / logo © 2022 Grokbase