Ranges and the [1,2,..,n] notation¶
AUTHORS:
Jeroen Demeyer (2016-02-22): moved here from
misc.pyand 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 < endandstart+(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 ``coerceis true.coerce– convertstart,endandstepto the same universe (either the universe given inuniverseor the automatically detected universe)include_endpoint– whether or not to include the endpoint (default:False). This is only relevant ifendis actually of the formstart + k*stepfor 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
srangeto distinguish it from the built-in Pythonrangecommand. 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 < endandstart+(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,endandstepto the same universe (either the universe given inuniverseor the automatically detected universe)include_endpoint– whether or not to include the endpoint (default:False). This is only relevant ifendis actually of the formstart + k*stepfor 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(),startandendcan 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*stepis fuzzy for an inexact ring. Ifstart + k*step = endfor some \(k\) withinendpoint_toleranceof 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.