Ask Your Question
1

How can we sum over decimal numbers?

asked 2015-10-08 13:32:09 -0500

suraj gravatar image

I know that for summing over integers from 1 to n we have sum(f,x,1,4) type of thing ...but what if I want to sum like f(1)+f(1.1)+f(1.2)+...+f(3.9)+f(4.0)? Can we create list of numbers from 1 to 4 with step size 0.1 or arbitrary step size which I choose.? what is the command for that?

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
1

answered 2015-10-08 15:22:32 -0500

tmonteil gravatar image

updated 2015-10-08 15:30:35 -0500

Depending on how sensitive is your map f you should notice that 0.1 is a floating-point approximation of 1/10, which is not equal to 1/10 since the numbers are represented in binary format and that 1/10 can not be written as p/2^q for some integers p and q. So, perhaps (depending on your application, the required speed, the required accuracy,...) you should use the exact (rational) 1/10 instead of the numerical 0.1. The following example could be convincing:

sage: decimal = 0.1
sage: sum([decimal for i in  range(10)])
1.00000000000000
sage: sum([decimal for i in  range(10)]) == 1
False

Sage offers a srange function that produces the list of numbers you want:

sage: srange(1,4, step = 1/10)
[1,
 11/10,
 6/5,
 13/10,
 7/5,
 3/2,
 8/5,
 17/10,
 9/5,
 19/10,
 2,
 21/10,
 11/5,
 23/10,
 12/5,
 5/2,
 13/5,
 27/10,
 14/5,
 29/10,
 3,
 31/10,
 16/5,
 33/10,
 17/5,
 7/2,
 18/5,
 37/10,
 19/5,
 39/10]

To be compared with:

sage: srange(1,4, step = 0.1)
[1.00000000000000,
 1.10000000000000,
 1.20000000000000,
 1.30000000000000,
 1.40000000000000,
 1.50000000000000,
 1.60000000000000,
 1.70000000000000,
 1.80000000000000,
 1.90000000000000,
 2.00000000000000,
 2.10000000000000,
 2.20000000000000,
 2.30000000000000,
 2.40000000000000,
 2.50000000000000,
 2.60000000000000,
 2.70000000000000,
 2.80000000000000,
 2.90000000000000,
 3.00000000000000,
 3.10000000000000,
 3.20000000000000,
 3.30000000000000,
 3.40000000000000,
 3.50000000000000,
 3.60000000000000,
 3.70000000000000,
 3.80000000000000,
 3.90000000000000]

Be careful, that the last value (4 in this case) is not produced by default. If you want it, you should use the include_endpoint option:

So, you can get your sum as either:

sage: decimal = 0.1
sage: sum([f(i) for i in srange(1, 4, step=decimal, include_endpoint=True)])

or,

sage: decimal = 1/10
sage: sum([f(i) for i in srange(1, 4, step=decimal, include_endpoint=True)])

In that way, both the lists [f(i) for i in srange(1,4, step=decimal, include_endpoint=True)] and srange(1,4, step=decimal, include_endpoint=True) are produced and stored in memory befire the sum is computed. If, instead of 4 you plan to use a very big number, you may want to avoid storing them but only sum them, you can use iterators instead of lists, it suffice to replace srange with xsrange and [...] with (...), so you could write:

sage: sum((f(i) for i in xsrange(1, 4, step=decimal, include_endpoint=True)))
edit flag offensive delete link more
0

answered 2015-10-08 14:07:30 -0500

fidbc gravatar image

It shouldn't be hard to implement a "float version" of range. For example

def frange(a,b,n):
    return [a+(b-a)*i/n for i in range(n)]

can get you started.

If you are not willing to implement your own version, then you can just use numpy's linspace or numpy's arange.

Whatever choice you make you can just add the values in the list using sum ... type of thing.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2015-10-08 13:32:09 -0500

Seen: 64 times

Last updated: Oct 08 '15