# How can we sum over decimal numbers?

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 close merge delete

Sort by » oldest newest most voted

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)))

more

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.

more