Ranges and the [1,2,..,n]
notation¶
AUTHORS:
Jeroen Demeyer (2016-02-22): moved here from
misc.py
and cleaned up.
- sage.arith.srange.ellipsis_iter(step=None, *args)[source]¶
Same as ellipsis_range, but as an iterator (and may end with an Ellipsis).
See also ellipsis_range.
Use (1,2,…) notation.
EXAMPLES:
sage: A = ellipsis_iter(1,2,Ellipsis) sage: [next(A) for _ in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] sage: next(A) 11 sage: A = ellipsis_iter(1,3,5,Ellipsis) sage: [next(A) for _ in range(10)] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] sage: A = ellipsis_iter(1,2,Ellipsis,5,10,Ellipsis) sage: [next(A) for _ in range(10)] [1, 2, 3, 4, 5, 10, 11, 12, 13, 14]
>>> from sage.all import * >>> A = ellipsis_iter(Integer(1),Integer(2),Ellipsis) >>> [next(A) for _ in range(Integer(10))] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> next(A) 11 >>> A = ellipsis_iter(Integer(1),Integer(3),Integer(5),Ellipsis) >>> [next(A) for _ in range(Integer(10))] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] >>> A = ellipsis_iter(Integer(1),Integer(2),Ellipsis,Integer(5),Integer(10),Ellipsis) >>> [next(A) for _ in range(Integer(10))] [1, 2, 3, 4, 5, 10, 11, 12, 13, 14]
- sage.arith.srange.ellipsis_range(step=None, *args)[source]¶
Return arithmetic sequence determined by the numeric arguments and ellipsis. Best illustrated by examples.
Use [1,2,..,n] notation.
EXAMPLES:
sage: ellipsis_range(1,Ellipsis,11,100) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100] sage: ellipsis_range(0,2,Ellipsis,10,Ellipsis,20) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sage: ellipsis_range(0,2,Ellipsis,11,Ellipsis,20) [0, 2, 4, 6, 8, 10, 11, 13, 15, 17, 19] sage: ellipsis_range(0,2,Ellipsis,11,Ellipsis,20, step=3) [0, 2, 5, 8, 11, 14, 17, 20] sage: ellipsis_range(10,Ellipsis,0) []
>>> from sage.all import * >>> ellipsis_range(Integer(1),Ellipsis,Integer(11),Integer(100)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100] >>> ellipsis_range(Integer(0),Integer(2),Ellipsis,Integer(10),Ellipsis,Integer(20)) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] >>> ellipsis_range(Integer(0),Integer(2),Ellipsis,Integer(11),Ellipsis,Integer(20)) [0, 2, 4, 6, 8, 10, 11, 13, 15, 17, 19] >>> ellipsis_range(Integer(0),Integer(2),Ellipsis,Integer(11),Ellipsis,Integer(20), step=Integer(3)) [0, 2, 5, 8, 11, 14, 17, 20] >>> ellipsis_range(Integer(10),Ellipsis,Integer(0)) []
- sage.arith.srange.srange(*args, **kwds)[source]¶
Return a list of numbers
start, start+step, ..., start+k*step
, wherestart+k*step < end
andstart+(k+1)*step >= end
.This provides one way to iterate over Sage integers as opposed to Python int’s. It also allows you to specify step sizes for such an iteration.
INPUT:
start
– number (default: 0)end
– numberstep
– number (default: 1)universe -- parent or type where all the elements should live (default: deduce from inputs). This is only used if ``coerce
is true.coerce
– convertstart
,end
andstep
to the same universe (either the universe given inuniverse
or the automatically detected universe)include_endpoint
– whether or not to include the endpoint (default:False
). This is only relevant ifend
is actually of the formstart + k*step
for some integer \(k\).
- `
endpoint_tolerance
– used to determine whether or not the endpoint is hit for inexact rings (default:
1e-5
)
OUTPUT: list
Note
This function is called
srange
to distinguish it from the built-in Pythonrange
command. The s at the beginning of the name stands for “Sage”.EXAMPLES:
sage: v = srange(5); v [0, 1, 2, 3, 4] sage: type(v[2]) <class 'sage.rings.integer.Integer'> sage: srange(1, 10) [1, 2, 3, 4, 5, 6, 7, 8, 9] sage: srange(10, 1, -1) [10, 9, 8, 7, 6, 5, 4, 3, 2] sage: srange(10,1,-1, include_endpoint=True) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] sage: srange(1, 10, universe=RDF) [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] sage: srange(1, 10, 1/2) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] sage: # needs sage.rings.real_mpfr sage: srange(1, 5, 0.5) [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] sage: srange(0, 1, 0.4) [0.000000000000000, 0.400000000000000, 0.800000000000000] sage: srange(1.0, 5.0, include_endpoint=True) [1.00000000000000, 2.00000000000000, 3.00000000000000, 4.00000000000000, 5.00000000000000] sage: srange(1.0, 1.1) [1.00000000000000] sage: srange(1.0, 1.0) [] sage: V = VectorSpace(QQ, 2) # needs sage.modules sage: srange(V([0,0]), V([5,5]), step=V([2,2])) # needs sage.modules [(0, 0), (2, 2), (4, 4)]
>>> from sage.all import * >>> v = srange(Integer(5)); v [0, 1, 2, 3, 4] >>> type(v[Integer(2)]) <class 'sage.rings.integer.Integer'> >>> srange(Integer(1), Integer(10)) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> srange(Integer(10), Integer(1), -Integer(1)) [10, 9, 8, 7, 6, 5, 4, 3, 2] >>> srange(Integer(10),Integer(1),-Integer(1), include_endpoint=True) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] >>> srange(Integer(1), Integer(10), universe=RDF) [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] >>> srange(Integer(1), Integer(10), Integer(1)/Integer(2)) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] >>> # needs sage.rings.real_mpfr >>> srange(Integer(1), Integer(5), RealNumber('0.5')) [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] >>> srange(Integer(0), Integer(1), RealNumber('0.4')) [0.000000000000000, 0.400000000000000, 0.800000000000000] >>> srange(RealNumber('1.0'), RealNumber('5.0'), include_endpoint=True) [1.00000000000000, 2.00000000000000, 3.00000000000000, 4.00000000000000, 5.00000000000000] >>> srange(RealNumber('1.0'), RealNumber('1.1')) [1.00000000000000] >>> srange(RealNumber('1.0'), RealNumber('1.0')) [] >>> V = VectorSpace(QQ, Integer(2)) # needs sage.modules >>> srange(V([Integer(0),Integer(0)]), V([Integer(5),Integer(5)]), step=V([Integer(2),Integer(2)])) # needs sage.modules [(0, 0), (2, 2), (4, 4)]
Including the endpoint:
sage: srange(0, 10, step=2, include_endpoint=True) [0, 2, 4, 6, 8, 10] sage: srange(0, 10, step=3, include_endpoint=True) [0, 3, 6, 9]
>>> from sage.all import * >>> srange(Integer(0), Integer(10), step=Integer(2), include_endpoint=True) [0, 2, 4, 6, 8, 10] >>> srange(Integer(0), Integer(10), step=Integer(3), include_endpoint=True) [0, 3, 6, 9]
Try some inexact rings:
sage: srange(0.5, 1.1, 0.1, universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999] sage: srange(0.5, 1, 0.1, universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999] sage: srange(0.5, 0.9, 0.1, universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999] sage: srange(0, 1.1, 0.1, universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.1] sage: srange(0, 0.2, 0.1, universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2] sage: srange(0, 0.3, 0.1, universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2, 0.3]
>>> from sage.all import * >>> srange(RealNumber('0.5'), RealNumber('1.1'), RealNumber('0.1'), universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999] >>> srange(RealNumber('0.5'), Integer(1), RealNumber('0.1'), universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999] >>> srange(RealNumber('0.5'), RealNumber('0.9'), RealNumber('0.1'), universe=RDF, include_endpoint=False) [0.5, 0.6, 0.7, 0.7999999999999999] >>> srange(Integer(0), RealNumber('1.1'), RealNumber('0.1'), universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.1] >>> srange(Integer(0), RealNumber('0.2'), RealNumber('0.1'), universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2] >>> srange(Integer(0), RealNumber('0.3'), RealNumber('0.1'), universe=RDF, include_endpoint=True) [0.0, 0.1, 0.2, 0.3]
More examples:
sage: Q = RationalField() sage: srange(1, 10, Q('1/2')) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] sage: srange(1, 5, 0.5) # needs sage.rings.real_mpfr [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] sage: srange(0, 1, 0.4) # needs sage.rings.real_mpfr [0.000000000000000, 0.400000000000000, 0.800000000000000]
>>> from sage.all import * >>> Q = RationalField() >>> srange(Integer(1), Integer(10), Q('1/2')) [1, 3/2, 2, 5/2, 3, 7/2, 4, 9/2, 5, 11/2, 6, 13/2, 7, 15/2, 8, 17/2, 9, 19/2] >>> srange(Integer(1), Integer(5), RealNumber('0.5')) # needs sage.rings.real_mpfr [1.00000000000000, 1.50000000000000, 2.00000000000000, 2.50000000000000, 3.00000000000000, 3.50000000000000, 4.00000000000000, 4.50000000000000] >>> srange(Integer(0), Integer(1), RealNumber('0.4')) # needs sage.rings.real_mpfr [0.000000000000000, 0.400000000000000, 0.800000000000000]
Negative steps are also allowed:
sage: srange(4, 1, -1) [4, 3, 2] sage: srange(4, 1, -1/2) [4, 7/2, 3, 5/2, 2, 3/2]
>>> from sage.all import * >>> srange(Integer(4), Integer(1), -Integer(1)) [4, 3, 2] >>> srange(Integer(4), Integer(1), -Integer(1)/Integer(2)) [4, 7/2, 3, 5/2, 2, 3/2]
- sage.arith.srange.xsrange(start, end=None, step=1, universe=None, coerce=True, include_endpoint=False, endpoint_tolerance=1e-05)[source]¶
Return an iterator over numbers
start, start+step, ..., start+k*step
, wherestart+k*step < end
andstart+(k+1)*step >= end
.This provides one way to iterate over Sage integers as opposed to Python int’s. It also allows you to specify step sizes for such an iteration.
INPUT:
start
– number (default: 0)end
– numberstep
– number (default: 1)universe
– parent or type where all the elements should live (default: deduce from inputs)coerce
– convertstart
,end
andstep
to the same universe (either the universe given inuniverse
or the automatically detected universe)include_endpoint
– whether or not to include the endpoint (default:False
). This is only relevant ifend
is actually of the formstart + k*step
for some integer \(k\).
- `
endpoint_tolerance
– used to determine whether or not the endpoint is hit for inexact rings (default: 1e-5)
OUTPUT: iterator
Unlike
range()
,start
andend
can be any type of numbers, and the resulting iterator involves numbers of that type.Warning
You need to be careful when using this function over inexact rings: the elements are computed via repeated addition rather than multiplication, which may produce slightly different results. For example:
sage: sum([1.1] * 10) == 1.1 * 10 False
>>> from sage.all import * >>> sum([RealNumber('1.1')] * Integer(10)) == RealNumber('1.1') * Integer(10) False
Also, the question of whether the endpoint is hit exactly for a given
start + k*step
is fuzzy for an inexact ring. Ifstart + k*step = end
for some \(k\) withinendpoint_tolerance
of being integral, it is considered an exact hit, thus avoiding spurious values falling just below the endpoint.EXAMPLES:
sage: xsrange(10) <...generator object at 0x...> sage: for i in xsrange(1,5): ....: print(i) 1 2 3 4
>>> from sage.all import * >>> xsrange(Integer(10)) <...generator object at 0x...> >>> for i in xsrange(Integer(1),Integer(5)): ... print(i) 1 2 3 4
See
srange()
for more examples.