pycommons.math package

Common maths routines.

Submodules

pycommons.math.int_math module

Mathematics routines combining integers and floats.

These routines try to return results with the highest possible precision, ideally as integers. If floating point values need to be converted to integers, then we round towards the nearest integer numbers, whereas 0.5 is always rounded up and -0.5 is always rounded down. Thus, 1.5 becomes 2 and -1.5 becomes -2.

pycommons.math.int_math.ceil_div(a, b)[source]

Compute a ceiling division of two integers.

Parameters:
  • a (int) – the number to be divided by b

  • b (int) – the number dividing a

Return type:

int

Returns:

the rounded-up result of the division

>>> ceil_div(1, 1)
1
>>> ceil_div(-1, 1)
-1
>>> ceil_div(-1, -1)
1
>>> ceil_div(1, -1)
-1
>>> ceil_div(98, 98)
1
>>> ceil_div(98, 99)
1
>>> ceil_div(98, 97)
2
>>> ceil_div(98, -97)
-1
>>> ceil_div(-98, -97)
2
>>> ceil_div(-98, 97)
-1
>>> ceil_div(3, 1)
3
>>> ceil_div(3, -1)
-3
>>> ceil_div(-3, 1)
-3
>>> ceil_div(-3, -1)
3
>>> ceil_div(3, 2)
2
>>> ceil_div(3, -2)
-1
>>> ceil_div(-3, 2)
-1
>>> ceil_div(-3, -2)
2
>>> ceil_div(3, 3)
1
>>> ceil_div(3, 4)
1
>>> ceil_div(3, -4)
0
>>> ceil_div(-3, 4)
0
>>> ceil_div(-3, -4)
1
>>> ceil_div(4, 1)
4
>>> ceil_div(4, 2)
2
>>> ceil_div(4, 3)
2
>>> ceil_div(4, 4)
1
>>> ceil_div(4, 5)
1
>>> ceil_div(4, 23242398)
1
>>> ceil_div(4, -23242398)
0
>>> ceil_div(-4, 23242398)
0
>>> ceil_div(-4, -23242398)
1
>>> ceil_div(0, 1)
0
>>> ceil_div(0, -1)
0
>>> ceil_div(-0, 1)
0
>>> ceil_div(-0, -1)
0
>>> try:
...     ceil_div(1, 0)
... except ZeroDivisionError as ze:
...     print(ze)
integer division or modulo by zero
>>> try:
...     ceil_div(-1, 0)
... except ZeroDivisionError as ze:
...     print(ze)
integer division or modulo by zero
>>> try:
...     ceil_div(1, -0)
... except ZeroDivisionError as ze:
...     print(ze)
integer division or modulo by zero
>>> try:
...     ceil_div(-1, -0)
... except ZeroDivisionError as ze:
...     print(ze)
integer division or modulo by zero
pycommons.math.int_math.float_to_frac(value)[source]

Turn a floating point number into an integer fraction.

If we want to translate a floating point number to an integer fraction, then we have several possible ways to go about this. The reason is that, due to the loss in precision when representing fractions as floating point numbers, several different integer fractions can produce the exactly same floating point number.

One choice would be to use float.as_integer_ratio(), which turns the binary representation of the floating point number to an integer fraction. This is the canonical way that, without losing any precision, will return an integer fraction that fits exactly to the floating point value.

However, as said, there may be multiple such fractions. And some of them may be more “compact” than others.

A second approach would be to first represent the floating point value as a string. The string that this produces also represents exactly this floating point value, obviously. Now we can translate the string to a fraction - and this can give us a different result.

Which of the two is right?

Both of them are. Kind of. So I’d figure we test both and stick with the float.as_integer_ratio() default result - unless the string path provides a more compact representation. As simple yard stick let’s use |numerator| + denominator and pick whichever fraction gives us the smallest value.

Parameters:

value (int | float) – the floating point value

Return type:

tuple[int, int]

Returns:

the integer fraction

Raises:
>>> float_to_frac(0.1)
(1, 10)
>>> float_to_frac(1e-1)
(1, 10)
>>> float_to_frac(1e-20)
(1, 100000000000000000000)
>>> 1e-20.as_integer_ratio()
(6646139978924579, 664613997892457936451903530140172288)
>>> float_to_frac(1e-30)
(1, 1000000000000000000000000000000)
>>> float_to_frac(1e30)
(1000000000000000000000000000000, 1)
>>> float_to_frac(1000)
(1000, 1)
>>> float_to_frac(1000.567)
(1000567, 1000)
>>> float_to_frac(1.234e-5)
(617, 50000000)
>>> float_to_frac(1.234e5)
(123400, 1)
>>> float_to_frac(0)
(0, 1)
>>> 0 / 1
0.0
>>> float_to_frac(-5376935265607590)
(-5376935265607590, 1)
>>> -5376935265607590 / 1
-5376935265607590.0
>>> float_to_frac(4)
(4, 1)
>>> 4 / 1
4.0
>>> float_to_frac(-21844.45693689149)
(-2184445693689149, 100000000000)
>>> -2184445693689149 / 100000000000
-21844.45693689149
>>> float_to_frac(-3010907.436657168)
(-188181714791073, 62500000)
>>> -188181714791073 / 62500000
-3010907.436657168
>>> float_to_frac(13660.023207762431)
(1877419294078101, 137438953472)
>>> 1877419294078101 / 137438953472
13660.023207762431
>>> float_to_frac(438027.68586526066)
(58791080797933, 134217728)
>>> 58791080797933 / 134217728
438027.68586526066
>>> float_to_frac(-8338355882.478134)
(-546462491114087, 65536)
>>> -546462491114087 / 65536
-8338355882.478134
>>> float_to_frac(-32835294.95774138)
(-275442417964869, 8388608)
>>> -275442417964869 / 8388608
-32835294.95774138
>>> float_to_frac(-0.8436071305882418)
(-3799268758964299, 4503599627370496)
>>> -3799268758964299 / 4503599627370496
-0.8436071305882418
>>> float_to_frac(-971533.786640197)
(-32599264379521, 33554432)
>>> -32599264379521 / 33554432
-971533.786640197
>>> float_to_frac(187487280836.01147)
(767947902304303, 4096)
>>> 767947902304303 / 4096
187487280836.01147
>>> float_to_frac(24214223389953.125)
(193713787119625, 8)
>>> 193713787119625 / 8
24214223389953.125
>>> float_to_frac(2645.112807929305)
(363541536137187, 137438953472)
>>> 363541536137187 / 137438953472
2645.112807929305
>>> float_to_frac(92129361.64291245)
(1545674200225257, 16777216)
>>> 1545674200225257 / 16777216
92129361.64291245
>>> float_to_frac(7218177.564653773)
(1937614786056805, 268435456)
>>> 1937614786056805 / 268435456
7218177.564653773
>>> float_to_frac(-1.4589908563595052e+16)
(-14589908563595052, 1)
>>> -14589908563595052 / 1
-1.4589908563595052e+16
>>> float_to_frac(-1.607745417434216e+16)
(-16077454174342160, 1)
>>> -16077454174342160 / 1
-1.607745417434216e+16
>>> float_to_frac(-952261813.8291152)
(-595163633643197, 625000)
>>> -595163633643197 / 625000
-952261813.8291152
>>> float_to_frac(124.69515801820336)
(779344737613771, 6250000000000)
>>> 779344737613771 / 6250000000000
124.69515801820336
>>> float_to_frac(1.041491959175676e+16)
(10414919591756760, 1)
>>> 10414919591756760 / 1
1.041491959175676e+16
>>> float_to_frac(1.4933667846659504e+16)
(14933667846659504, 1)
>>> 14933667846659504 / 1
1.4933667846659504e+16
>>> float_to_frac(-6.034817133993009e-05)
(-271784001959, 4503599627370496)
>>> -271784001959 / 4503599627370496
-6.034817133993009e-05
>>> float_to_frac(-2.682658826813622e-05)
(-1887753327, 70368744177664)
>>> -1887753327 / 70368744177664
-2.682658826813622e-05
>>> float_to_frac(6.342974725370709e-05)
(17853886631, 281474976710656)
>>> 17853886631 / 281474976710656
6.342974725370709e-05
>>> float_to_frac(8.759559844406795e-05)
(3081996129, 35184372088832)
>>> 3081996129 / 35184372088832
8.759559844406795e-05
>>> float_to_frac(-9.6e-09)
(-3, 312500000)
>>> -3 / 312500000
-9.6e-09
>>> float_to_frac(-0.4)
(-2, 5)
>>> -2 / 5
-0.4
>>> float_to_frac(2e-10)
(1, 5000000000)
>>> 1 / 5000000000
2e-10
>>> float_to_frac(0.3)
(3, 10)
>>> 3 / 10
0.3
>>> float_to_frac(-3e-09)
(-3, 1000000000)
>>> -3 / 1000000000
-3e-09
>>> float_to_frac(1e-07)
(1, 10000000)
>>> 1 / 10000000
1e-07
>>> float_to_frac(-8e-08)
(-1, 12500000)
>>> -1 / 12500000
-8e-08
>>> float_to_frac(-0.01)
(-1, 100)
>>> -1 / 100
-0.01
>>> float_to_frac(1e-08)
(1, 100000000)
>>> 1 / 100000000
1e-08
>>> float_to_frac(0.01)
(1, 100)
>>> 1 / 100
0.01
>>> float_to_frac(-2e-06)
(-1, 500000)
>>> -1 / 500000
-2e-06
>>> float_to_frac(-6e-08)
(-3, 50000000)
>>> -3 / 50000000
-6e-08
>>> float_to_frac(7e-05)
(7, 100000)
>>> 7 / 100000
7e-05
>>> float_to_frac(-1e+40)
(-10000000000000000000000000000000000000000, 1)
>>> -10000000000000000000000000000000000000000 / 1
-1e+40
>>> float_to_frac(1e+40)
(10000000000000000000000000000000000000000, 1)
>>> 10000000000000000000000000000000000000000 / 1
1e+40
pycommons.math.int_math.try_float_int_div(a, b)[source]

Try to divide a float by an int at best precision.

Parameters:
  • a (int | float) – the first number, which is either a float or an int

  • b (int) – the second number, which must be an int

Return type:

int | float

Returns:

a/b, but always finite

Raises:
  • ValueError – if either one of the arguments or the final result would not be finite

  • TypeError – if either one of a or b is neither an integer nor a float

>>> try_float_int_div(10, 2)
5
>>> try_float_int_div(10.0, 2)
5
>>> try_float_int_div(10, 3)
3.3333333333333335
>>> try_float_int_div(-10, 2)
-5
>>> try_float_int_div(-10.2, 2)
-5.1
>>> try_float_int_div(-10.0, 2)
-5
>>> try_float_int_div(-10, 3)
-3.3333333333333335
>>> print(type(try_float_int_div(10.0, 2)))
<class 'int'>
>>> print(type(try_float_int_div(10.0, 3)))
<class 'float'>
>>> try:
...     try_float_int_div(10, 0.5)
... except TypeError as te:
...     print(te)
b should be an instance of int but is float, namely 0.5.
>>> from math import inf, nan
>>> try:
...     try_float_int_div(1.0, 0)
... except ZeroDivisionError as zde:
...     print(zde)
integer division or modulo by zero
>>> try:
...     try_float_int_div(inf, 0)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is inf.
>>> try:
...     try_float_int_div(-inf, 0)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is -inf.
>>> try:
...     try_float_int_div(nan, 0)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is nan.
>>> try:
...     try_float_int_div(1, inf)
... except TypeError as te:
...     print(te)
b should be an instance of int but is float, namely inf.
>>> try:
...     try_float_int_div("y", 1)
... except TypeError as te:
...     print(te)
value should be an instance of any in {float, int} but is str, namely 'y'.
>>> try:
...     try_float_int_div(1, "x")
... except TypeError as te:
...     print(te)
b should be an instance of int but is str, namely 'x'.
pycommons.math.int_math.try_int(value)[source]

Attempt to convert a float to an integer.

This method will convert a floating point number to an integer if the floating point number was representing an exact integer. This is the case if it has a) no fractional part and b) is in the range -9007199254740992…9007199254740992, i.e., the range where +1 and -1 work without loss of precision.

Parameters:

value (int | float) – the input value, which must either be int or float

Return type:

int | float

Returns:

an int if value can be represented as int without loss of precision, val otherwise

Raises:
  • TypeError – if value is neither an instance of int nor of float

  • ValueError – if value is a float, but not finite

>>> print(type(try_int(10.5)))
<class 'float'>
>>> print(type(try_int(10)))
<class 'int'>
>>> from math import inf, nan, nextafter
>>> type(try_int(0.0))
<class 'int'>
>>> type(try_int(0.5))
<class 'float'>
>>> try:
...     try_int(inf)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is inf.
>>> try:
...     try_int(-inf)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is -inf.
>>> try:
...     try_int(nan)
... except ValueError as ve:
...     print(ve)
Value must be finite, but is nan.
>>> try:
...     try_int("blab")  # noqa  # type: off
... except TypeError as te:
...     print(te)
value should be an instance of any in {float, int} but is str, namely 'blab'.
>>> type(try_int(9007199254740992.0))
<class 'int'>
>>> try_int(9007199254740992.0)
9007199254740992
>>> too_big = nextafter(9007199254740992.0, inf)
>>> print(too_big)
9007199254740994.0
>>> type(try_int(too_big))
<class 'float'>
>>> type(try_int(-9007199254740992.0))
<class 'int'>
>>> try_int(-9007199254740992.0)
-9007199254740992
>>> type(try_int(-too_big))
<class 'float'>
pycommons.math.int_math.try_int_add(a, b)[source]

Try to add a floating point number to an integer.

Parameters:
  • a (int) – the integer

  • b (int | float) – the floating point number

Return type:

int | float

Returns:

a + b or the best possible approximation thereof

Raises:
  • TypeError – if a is not an integer or if b is neither a float nor an integer

  • ValueError – if b or the result is not finite

>>> try_int_add(0, -8670.320148166094)
-8670.320148166094
>>> 0 + -8670.320148166094
-8670.320148166094
>>> try_int_add(-63710, 100.96227261264141)
-63609.03772738736
>>> -63710 + 100.96227261264141
-63609.03772738736
>>> try_int_add(77, 12975.955050422272)
13052.955050422272
>>> 77 + 12975.955050422272
13052.955050422272
>>> try_int_add(-308129344193738, 62995516.01169562)
-308129281198222
>>> -308129344193738 + 62995516.01169562
-308129281198222.0
>>> try_int_add(-2158504468760619, -1.3773316665252534e+16)
-1.5931821134013152e+16
>>> -2158504468760619 + -1.3773316665252534e+16
-1.5931821134013152e+16
>>> try_int_add(-960433622582960, 1.491132239895968e+16)
1.395088877637672e+16
>>> -960433622582960 + 1.491132239895968e+16
1.395088877637672e+16

# exact result: 10796862382206072.70684135 >>> try_int_add(10796862236149287, 146056785.70684135) 10796862382206073 >>> 10796862236149287 + 146056785.70684135 1.0796862382206074e+16

# exact result: -11909678744561796.5206623 >>> try_int_add(-11909677351933537, -1392628259.5206623) -11909678744561797 >>> -11909677351933537 + -1392628259.5206623 -1.1909678744561796e+16

# exact result: 8991519996993845.25 >>> try_int_add(9257476766666634, -265956769672788.75) 8991519996993845 >>> 9257476766666634 + -265956769672788.75 8991519996993845.0

>>> v = int("-91666501312414085408333198553755526631169610879455816489173691561634548053405237489064")
>>> try_int_add(v, 6.147962494740932e+217)
6.147962494740932e+217
>>> v + 6.147962494740932e+217
6.147962494740932e+217

exact result: 20601962663817202800007836095739946419534015091420431778715465940577471030.192914550695235 >>> v = int(“20601962663817202800007836095739946419534015091420431778715465940577470980”) >>> try_int_add(v, 50.192914550695235) 20601962663817202800007836095739946419534015091420431778715465940577471030 >>> v + 50.192914550695235 2.0601962663817203e+73

>>> try:
...     try_int_add(2.0, 1)
... except TypeError as te:
...     print(te)
a should be an instance of int but is float, namely 2.0.
>>> try:
...     try_int_add(2, "1")
... except TypeError as te:
...     print(te)
b should be an instance of any in {float, int} but is str, namely '1'.
>>> from math import inf
>>> try:
...     try_int_add(2, inf)
... except ValueError as ve:
...     print(ve)
b=inf is not finite
pycommons.math.int_math.try_int_div(a, b)[source]

Try to divide two integers at best precision.

Floating point divisions can incur some loss of precision. We try to avoid this here as much as possible. First, we check if a is divisible by b without any fractional part. If this is true, then we can do a pure integer division without loss of any precision. In other words, if a % b == 0, then a / b is itself an integer, i.e., can be represented exactly.

Otherwise, it will have a fractional part, so it would ideally be a float. Well.

What if the integer a is really large? Converting it to floating point number may then incur a loss of precision. And why do we convert it to a float in the first place? To properly represent the fractional part. Because the integer part is a // b is an integer. The fractional part f is then by definition f = (a % b) // b == (a - b*(a // b)) / b. Obviously, 0<f<1. It may be entirely possible that we lose several full integer digits by converting the integer a to a float … just to then be able to add a fraction f. So this loss of precision may be much larger than the little fractional part that we would add (which will always be in (0, 1). In such a case, it may be much better to stay in the realm of integers and instead lose the fractional part. Thus, we also test whether multiplying the result of the floating point computation with b is closer to a than integer results rounded in either direction.

During this procedure, we try to pick the result closest to the original value. This, however, may only be possible if we can actually compute the difference. If we deal with floating point numbers and integers, some integers may simply be too large for being ever converted to a float. In this case, we remain entirely in the integer realm and only round if need be.

Parameters:
  • a (int) – the first integer

  • b (int) – the second integer

Return type:

int | float

Returns:

a/b, either as int or as float but always a finite value

Raises:
>>> print(try_int_div(10, 2))
5
>>> print(try_int_div(10, -2))
-5
>>> print(try_int_div(-10, 2))
-5
>>> print(try_int_div(-10, -2))
5
>>> print(type(try_int_div(10, 2)))
<class 'int'>
>>> print(try_int_div(10, 3))
3.3333333333333335
>>> print(try_int_div(-10, 3))
-3.3333333333333335
>>> print(try_int_div(10, -3))
-3.3333333333333335
>>> print(try_int_div(-10, -3))
3.3333333333333335
>>> print(type(try_int_div(10, 3)))
<class 'float'>
>>> print(try_int_div(9007199254740992, 1))
9007199254740992
>>> print(try_int_div(2109792310235001520128, 234234))
9007199254740992
>>> print(try_int_div(2109792310235001520128, 234235))
9007160801054503
>>> print(try_int_div(2109792310235001520128, 234233))
9007237708755818
>>> large = 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> try:
...     large / 1
... except OverflowError as oe:
...     print(oe)
integer division result too large for a float
>>> try_int_div(large, 1)
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> try_int_div(large * 7, 1 * 7)
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> res = try_int_div(large, 7)
>>> print(res)
176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841
>>> large - (res * 7)
3
>>> res = try_int_div(large - 1, 7)
>>> print(res)
176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841
>>> (large - 1) - (res * 7)
2
>>> res = try_int_div(large + 1, 7)
>>> print(res)
176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366841446208112716049382700176366842
>>> (large + 1) - (res * 7)
-3
>>> try:
...     try_int_div(0, 0)
... except ZeroDivisionError as zde:
...     print(zde)
integer division or modulo by zero
>>> try:
...     try_int_div(1, 0)
... except ZeroDivisionError as zde:
...     print(zde)
integer division or modulo by zero
>>> try:
...     try_int_div(-1, 0)
... except ZeroDivisionError as zde:
...     print(zde)
integer division or modulo by zero
>>> try_int_div(153, 17)
9
>>> try_int_div(-153, 17)
-9
>>> try_int_div(626240198453350272215815210991, 180)
3479112213629723734532306728
>>> try_int_div(-626240198453350272215815210991, 180)
-3479112213629723734532306728
>>> try_int_div(312641328808813509022862142116, 184)
1699137656569638635993815990
>>> try_int_div(-312641328808813509022862142116, 184)
-1699137656569638635993815990
>>> try_int_div(300228563787891776398328530521, 6)
50038093964648629399721421754
>>> try_int_div(300228563787891776398328530520, 6)
50038093964648629399721421753
>>> try_int_div(-300228563787891776398328530521, 6)
-50038093964648629399721421754
>>> try_int_div(153, -17)
-9
>>> try_int_div(-153, -17)
9
>>> try_int_div(626240198453350272215815210991, -180)
-3479112213629723734532306728
>>> try_int_div(-626240198453350272215815210991, -180)
3479112213629723734532306728
>>> try_int_div(312641328808813509022862142116, -184)
-1699137656569638635993815990
>>> try_int_div(-312641328808813509022862142116, -184)
1699137656569638635993815990
>>> try_int_div(300228563787891776398328530521, -6)
-50038093964648629399721421754
>>> try_int_div(-300228563787891776398328530521, -6)
50038093964648629399721421754
>>> try_int_div(471560594207063922064065980174, 160)
2947253713794149512900412376
>>> try_int_div(7995687632, 605623302520652727304862084393)
1.3202410803417417e-20
>>> try_int_div(308201705551808339041017943851, 23)
13400074154426449523522519298
>>> try_int_div(899348944156468188933109403939, 54)
16654610076971633128390914888
>>> try_int_div(494818043590514116668712249977, 42)
11781381990250336111159815476
>>> try_int_div(738070379515233920, 205)
3600343314708458
>>> try_int_div(3502315235185234554036893628, 2914324106703)
1201759003787480
>>> try_int_div(7410628973168661103, 3869)
1915386139356076.8
>>> try_int_div(1230161216449799063065724370370, 4689247521470)
262336592559346126
>>> try_int_div(1052870426843577701006624798274, 28)
37602515244413489321665171367
>>> try_int_div(218235816140080518429116, 65180391)
3348182065064330.5
>>> try_int_div(542681063252950460111634072, 1417)
382978873149576894927053
>>> try_int_div(6347580784084238615827, 9508617)
667560885466754.9
>>> try_int_div(25864142832167873073008, 8621014)
3000127691727199.5
>>> try_int_div(35377667634669293542601414338, 8678403583)
4076517909811212054
>>> try_int_div(1423204593957046760175, 6)
237200765659507793363
>>> try_int_div(1959151753859121847452742, 155502)
12598884605079817928
>>> try_int_div(153429321515534965993379305, 15165212220)
10117189215010864
>>> try_int_div(638685779810794590594721888599, 6355644831674)
100491106209686119
>>> try_int_div(14634805, 3163458943542033136)
4.626203551614245e-12
>>> try_int_div(2728490692514068837390, 1134)
2406076448425104795
>>> try_int_div(52133244, 2145832361321597595907)
2.4295115005112346e-14
>>> try_int_div(989732710522254024, 870)
1137623805197993.2
>>> try_int_div(1015, 4100715151904)
2.475178017494646e-10
>>> try_int_div(750731, 60649291746)
1.2378231936228884e-05
>>> try_int_div(7972413701754221571302566, 1660418690)
4801447821425222
>>> try_int_div(356135676699525125944, 46208)
7707229845471025
>>> try_int_div(10448177882855961291672, 1739414)
6006722886475538
>>> try_int_div(739391142068058031063862, 8456)
87439822855730609161
>>> try_int_div(316514845935646909034735039673, 32172)
9838208564455020173900753
>>> try_int_div(4158458869534984918534998087, 30)
138615295651166163951166603
>>> try_int_div(102306108211747181839762853503, 29118)
3513500522417308257427119
>>> all(try_int_div(1, y) == (1 / y) for y in range(2, 10))
True
>>> all(try_int_div(2, y) == (2 / y) for y in range(3, 10))
True
>>> try_int_div(820432337843942760, 85)
9652145151105209
>>> try_int_div(84050617, 3577089862)
0.023496926340286613
>>> try_int_div(812060021745358856, 996816531)
814653445.7356013
>>> try_int_div(38029336, 472982612237)
8.040324319775297e-05
>>> try_int_div(50229909719349513, 9)
5581101079927724
>>> try_int_div(61320503685013026, 2728161164469337)
22.476862614874392
>>> try_int_div(23134400382350491, 8)
2891800047793811.5
>>> try_int_div(12510965, 67561917605841203)
1.8517776645993746e-10
>>> try_int_div(27246707584980173, 4)
6811676896245043
>>> try_int_div(135385235231741420, 6)
22564205871956903
>>> try_int_div(90, 153429501803)
5.865886217603572e-10
>>> try_int_div(734553401849288248, 951111)
772310909924.5916
>>> try_int_div(9820998979656, 4239082999146)
2.3167744018304255
>>> try_int_div(133105116441194557, 17)
7829712731834974
>>> try_int_div(1004604250960040176, 14)
71757446497145727
>>> try_int_div(246148731190755584, 6)
41024788531792597
>>> try_int_div(991564, 72057594037927936)
1.3760714789867734e-11
>>> try_int_div(2623725286393384, 139634775865757)
18.789912972079378
>>> try_int_div(63010439554808723, 9)
7001159950534303
>>> try_int_div(2801452, 427673)
6.550453266865105
>>> try_int_div(14177411351567, 349688426689780)
0.04054298132132421
>>> try_int_div(126660394112336947, 368)
344185853566133
>>> try_int_div(1031427640916897886, 7)
147346805845271127
>>> try_int_div(33290935002573849, 2)
16645467501286925
>>> try_int_div(209062743096233332, 64)
3266605360878646
>>> try_int_div(253174817711179642, 57)
4441663468617186.5
>>> try_int_div(29462133006911895, 24943246)
1181166757.8033707
>>> try_int_div(93475849985676023, 60673699562)
1540632.1134276118
>>> try_int_div(-16, -16)
1
>>> try_int_div(242, 150)
1.6133333333333333
>>> try_int_div(-547, -698)
0.7836676217765043
>>> try_int_div(463, 105)
4.40952380952381
>>> try_int_div(-148, -203)
0.729064039408867
>>> try_int_div(0, -25)
0
>>> try_int_div(24, -177)
-0.13559322033898305
>>> try_int_div(-166, 186)
-0.8924731182795699
>>> try_int_div(-608143760099358008316, 16)
-38008985006209875520
>>> try_int_div(-6917198296130591233, 2932)
-2359208150112753
>>> try_int_div(-40068404846647758412, 2431)
-16482272664190769
>>> try_int_div(809884532216820092, -80)
-10123556652710251
>>> try_int_div(-9428902965475478968, -1946)
4845273877428304
>>> try_int_div(94881103250893722164, 174)
545293696844216794
>>> try_int_div(558275776531402194, 196)
2848345798629603
>>> try_int_div(-5470954588630039684, -1425)
3839266377985993
>>> x = 52051907638184435686872083537997907834107397007408814104887055550626511625845155723435063364217885064987648273962363266643258572981136271430475196005811602816646869998761185517191667091818147736824340296222486666685948327106641344727853102203836313167806475289935694133683049416723665601922267867434230737563866877449592092646396784184383416539429598515786254896942626288280150268099746112877929289098786464747626881458668531793337750321167315312933603
>>> y = -139035476157512619782372181650126748736515125323507714345345535042071715351921681111638693456863646113210365045493352
>>> try_int_div(x, y)
-374378605207314720094873468836285633819929467061778300817269205498029513654024335132657459712666159214003174298773666703405454946223841058239933063485284313917060605484807243931457368242922416188904775387320134342062089255750862700497112616274728625215898978448963212698759159253800300962780904741771804645167943738988195771748632862162
>>> x = -237109974966504499065814155407507423756681813587992549276765875591466431785344954996723447284617738104563308335316636469414432945133872626562475145374718725305151916427038036160126112481184822188724826978273877612735658682500079452861107249299705282771925489140453114202884715335597378262368587555388033455119839506838214696423221276537787120528956164822252461892023157114027990382279583239059206677270588696258299518968279166470115508549546141742280327582498733595995697631187168710055335569609973997123439124471957303314220
>>> y = 2334357864974069231374511460880647203368457446428751178156068064378701796266433578371331497
>>> try_int_div(x, y)
-101573961098350440775039372298606794268469908577045401233130406288914282929188932483098022322818292556808620921656421644626989332901774307649479556618765285719954166516175417395319059113103751869677101061235848687846595854209154914381056640460582835505879418330902968200425941036454902030259440742425865934402069701651060764452872598704792440109834741980880533133349797622848020171153886834216445854191456742632611734684212485945595091
>>> x = 404100618846427932016026701491154140173947347613235450808470202962525253475728363668578430367548923168022182089413673609247435979940879600240187921742390653841150636438854369236710256224057607718115525186887758631639670824684023800548396685446620580303449643060159456830119838355315387882955924376571688222936921907566552043295097596971886346318138834494618220051900614717964461315530742161850062785306859778524746068148875909170944464910610460508750707051996751159775959805908309
>>> try_int_div(x, 455824846955327759894405021890034373481341853483437732)
886526089013377189427996129993958071440873972886348047699607747079616995543085620471927592765951912973058793385603301586629745150439814928912960267883664004127028245021824961458395565167629644085878157979069058008993075503852835979746848469931029741786475757184040552964154543887801327785586554297569583388146919245416237227940140677498927052487483630425657258239092995434299050034021769275549143357256693312576946435784210430
>>> x = -62329367861908430940060052330176958472405117526359796910825196228967182245151500849289063274091725415958639937290004620530027871949062475188176026655230475873682972201137642189143060727745274448518821915960488822897219191054331592679999119684641100513616523230906534113360817155818558407515396114454951055109084276990314617394966989996319564551198318944224505455969489515428690282113755080383328799009405959846487733552322199361433571441631699077621235779724223724145601506861527256455350316142
>>> y = -672227780379448967615099076221459579351218967417588220
>>> try_int_div(x, y)
92720607034011138790424924296260670427062526706986360227104870508211266764385374648400977097912400864248921190734351362277539276710856469258726616773893885766234994122772733590708011238049750176667082969644614903930265971589853266748072438948982007225613262945519147005987394933957619545642204000520363285890959448412497427025259922404568388012229950024924085644606386184930267142505617327729864850535306650812894643758024556770793387750201
>>> try:
...     try_int_div(1.0, 2)
... except TypeError as te:
...     print(te)
a should be an instance of int but is float, namely 1.0.
>>> try:
...     try_int_div(1, 2.0)
... except TypeError as te:
...     print(te)
b should be an instance of int but is float, namely 2.0.
pycommons.math.int_math.try_int_mul(a, b)[source]

Try to multiply an integer with an int or float as exactly as possible.

Parameters:
  • a (int) – the integer

  • b (int | float) – the int or float to multiply a with

Return type:

int | float

Returns:

a * b

Raises:
  • ValueError – if b or the result is not finite

  • TypeError – if a is not an integer or if b is neither an integer nor a float

# exact result: -111038109230780524.216538356 >>> try_int_mul(197262324754, -562895.673916714) -111038109230780524 >>> 197262324754 * -562895.673916714 -1.1103810923078053e+17

>>> try_int_mul(4, -2493374.0)
-9973496
>>> 4 * -2493374.0
-9973496.0

# exact result: -805144077682.7549712841791 >>> try_int_mul(609329061, -1321.3616897926931) -805144077682.755 >>> 609329061 * -1321.3616897926931 -805144077682.755

# exact result: -88939650274621002534.99 >>> try_int_mul(-6548165, 13582377700412.406) -88939650274621004172 >>> -6548165 * 13582377700412.406 -8.8939650274621e+19

>>> try_int_mul(4, 0.687279486538305)
2.74911794615322
>>> 4 * 0.687279486538305
2.74911794615322

# exact result: -2236563847561524626.733 >>> try_int_mul(21396228, -104530754091.86725) -2236563847561524627 >>> 21396228 * -104530754091.86725 -2.2365638475615245e+18

# exact result: -92649832027598387270282.5408 >>> try_int_mul(29187432758, -3174305626527.0176) -92649832027598386631807 >>> 29187432758 * -3174305626527.0176 -9.264983202759838e+22

# exact result: 47954872443652456553018463.12996 >>> try_int_mul(-317420410641789, -151076839534.96564) 47954872443652455666473176 >>> -317420410641789 * -151076839534.96564 4.795487244365246e+25

# exact result: 369200712310299349798.80066193866 >>> try_int_mul(8136505182920565, 45375.834465796564) 369200712310299353646 >>> 8136505182920565 * 45375.834465796564 3.6920071231029936e+20

# exact result: 431520767093145743090.73845486 >>> try_int_mul(40196153594795, 10735374.619252708) 431520767093145743091 >>> 40196153594795 * 10735374.619252708 4.315207670931457e+20

# exact result: -250242005217172713.52783326 >>> try_int_mul(27941562579, -8955905.90217194) -250242005217172703 >>> 27941562579 * -8955905.90217194 -2.502420052171727e+17

# exact result: -6563728914129924.848948421 >>> try_int_mul(-672426819, 9761253.906991959) -6563728914129925 >>> -672426819 * 9761253.906991959 -6563728914129925.0

>>> try_int_mul(14059, 1.0673811010650016e+16)
1.5006310899872858e+20
>>> 14059 * 1.0673811010650016e+16
1.5006310899872858e+20

# exact result: 14493050353163113.126430160675 >>> try_int_mul(240712887635, 60208.867483403505) 14493050353163113 >>> 240712887635 * 60208.867483403505 1.4493050353163114e+16

# exact result: 805460953505875910367.5205722154 >>> try_int_mul(1812115257906061, 444486.6020479314) 805460953505875915662 >>> 1812115257906061 * 444486.6020479314 8.054609535058759e+20

# exact result: -1384354228892504466.5554728510606 >>> try_int_mul(6815245310862468, -203.12610416033795) -1384354228892504435 >>> 6815245310862468 * -203.12610416033795 -1.3843542288925043e+18

# exact result: -572028608656496.423924280629596728 >>> try_int_mul(11587431214834713, -0.049366300265425656) -572028608656496.4 >>> 11587431214834713 * -0.049366300265425656 -572028608656496.4

# exact result: 1128618866534760.28918431873755142 >>> try_int_mul(16354919666787217, 0.06900791257487526) 1128618866534760.2 >>> 16354919666787217 * 0.06900791257487526 1128618866534760.2

# exact result: -2507326755278071.50624700782133248 >>> try_int_mul(13217245192529664, -0.18970116077556032) -2507326755278071.5 >>> 13217245192529664 * -0.18970116077556032 -2507326755278071.5

# exact result: 696151526057376.88027486041356184 >>> try_int_mul(-10333677547666606, -0.06736725844658964) 696151526057376.9 >>> -10333677547666606 * -0.06736725844658964 696151526057376.9

# exact result: -958450150333374.5128889837837098 >>> try_int_mul(12016909016999122, -0.0797584594322509) -958450150333374.6 >>> 12016909016999122 * -0.0797584594322509 -958450150333374.6

>>> aa = int("131853736830103986330358609231966527684353023330238338702287614652255017637688725497413841587504968776817592912265408771992845011229930897105528797412214008383330709731057075605034370259681835287681493225337651390572165677853314573952850041988465295832577950678186093485844861830998534026537308637591256017106983759509895599714369247370057549223306422774777546884919382044527420457991975491785609852030831998308070776211565814942350933642672902063132158594646597242361650005228312919254855")
>>> try_int_mul(aa, -2.6624992899981142e+135)
-351060480693750064453835292428076534998065626248205859394224131928297807375572486365608096664361429217283292718296360530276771619617508933170356074498812028442512109317126269695469503808824028263913213453615797077741562068054477787260819949647198753734696904695444416894546646340086090596255528370630342399126802523139567432239948562798671234539502947563959737236970890902877424384275539763076905795866685950545559899950633512202500980940635430054665554875703308334026066509069233835834019214049819194441000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

# exact result: 5115993211447460900.43715653698 >>> try_int_mul(45247701671134, 113066.36630145647) 5115993211447460734 >>> 45247701671134 * 113066.36630145647 5.115993211447461e+18

# exact result: -125197981872321984234 >>> try_int_mul(-15606149727, 8022349142.0) -125197981872321984234 >>> -15606149727 * 8022349142.0 -1.2519798187232199e+20

# exact result: -348481045.61578014504 >>> try_int_mul(6636, -52513.71995415614) -348481045.6157802 >>> 6636 * -52513.71995415614 -348481045.6157802

# exact result: -339789407482572717.3787168852228 >>> try_int_mul(6921658507965838, -49.0907500119406) -339789407482572714 >>> 6921658507965838 * -49.0907500119406 -3.3978940748257274e+17

>>> try_int_mul(2366231432701, 9061910680864392.0)
2.1442577893390244e+28
>>> 2366231432701 * 9061910680864392.0
2.1442577893390244e+28
>>> try_int_mul(11382697409900285, 7338977711.446167)
8.35373625873942e+25
>>> 11382697409900285 * 7338977711.446167
8.35373625873942e+25
>>> try_int_mul(34207518885, -6554.28955920917)
-224205983874406
>>> 34207518885 * -6554.28955920917
-224205983874406.0
>>> try_int_mul(35107, -165228482913.08173)
-5800676349629560
>>> 35107 * -165228482913.08173
-5800676349629560.0
>>> try_int_mul(0, 2.4281702332336544e+16)
0
>>> 0 * 2.4281702332336544e+16
0.0
>>> try_int_mul(12299117359251193, 9482167930204820.0)
1.1662229619371705e+32
>>> 12299117359251193 * 9482167930204820.0
1.1662229619371705e+32
>>> try_int_mul(-11025104822925196, 0.20926918490209712)
-2307214699753735.5
>>> -11025104822925196 * 0.20926918490209712
-2307214699753735.5
>>> try_int_mul(9772540954912922, -0.46316069211643107)
-4526256832413637
>>> 9772540954912922 * -0.46316069211643107
-4526256832413637.0
>>> a = -5687274133508874816611305835797802819969961090128107452007652532733682706778467556029446216090564515834530364339892682290523912804494560564153530543461393244816871985111746417931778069774416531277246135816681482485108855666554914988361150741132171265507858468795070096289596042533878836544303330516292056063762566783850836390861237578792994183593881591562639566572019685623123444496557488817481392619745509951116076463739023482649084091928996990245119032766058028744
>>> try_int_mul(a, 1.6152587208080178e+161)
-918641914177607285665947083878606106845874656349072400891265222608994894868393273335550289848260675410562832758047321131061871920910825594187776263381343874641691735191121376053894302947766400330740354558130054768809912753159801886275472082656621129808550544675347389062867415796970006219045528124169446067183418151530080010856381487158544646128107795979443668739119314808361766178939684712244126405728024628632359522637514215415356622397338073050018603468091162556851292634135491016372157121264877795675158627727964949024770274283909310368263635531679756438464790102625606997105530169121933171318181638719123552835758718976000
>>> a = 376560847831303570078539963816877133955751936352717499709764264061014957138918056943674235279041759617345256275395548431153753927815716233292447297269149929791925360073769054144096521088071580437368293552550840688369260826544997483426231840509951147268005485849616999574389651325135400971622625145852205361365860049799886307339513408795931018211062302039146270522678371572821101974821796182780210158355368107881592427373376547394885537235348770037983728077456443610490231815763426207048140659081123096064113083255321
>>> try_int_mul(a, 3.4397561272117625e+192)
1295277483595782578064922014384026983344842059086626186460671068451549982115342535199421721007878815369298874224123455721441548991298088516366970587695488452036367549015806771059851421087288034822321181634077733707983079645015388064200328289315831457596901453090747372964516534107621045874612822863305613446806304563553562786109972723062095583351926917494446975708601932868972870630036049038773314878254059872722527986124466136541209171400381061613153144818429564601085821078144985845210253549084934319770570473062886655875446136391274648488448957696316691763417067525251280127682030399365602278708061765108229023490122843782748129226917779112938304266733775179700489676013286505719242926784445427888800399360
>>> a = 129139500057625933922412781529753661193714022177289159193286727341869510538391068183373334814894358463049932698275602586001788553855337370614701810798567624656761308982494637834371899037091828942757328272879402878026516716840890321410558877108818475215456025987413249018189775618174448780086119164868545066265500186250891155310591180702358002
>>> try_int_mul(a, 1107055232.6334295)
142964559278459864122721473504338769103625425952771716003208051292041747018242273419932246881285681017872061407201342792874210512835357631625320661082072819079131257940844247255813910836282210665242651249270543058782206016019503066516405897455766109486696367661876404069863634518158697939624092648038619836809751492028454165243512720617990761805723389
>>> try_int_mul(1202489289292969, 2.1583639585424923e+306)
2595409542543320740382466696814772839397484966204401489986433673007511882740876153253237092741716795754997976766921219000512012754932543147420651232552021865590653560565352510903107437813105118562967695171401108727111667144608998274041055454528884056530194605604454257460607080594946316617996483736615341276121474415984640

# exact result: -7952338024951495584.4756757 >>> try_int_mul(-131722798246, 60371766.54947795) -7952338024951495584 >>> -131722798246 * 60371766.54947795 -7.952338024951496e+18

# exact result: 374987726685442496656857448.375 >>> try_int_mul(-197846874313873, -1895343194002.375) 374987726685442496656857448 >>> -197846874313873 * -1895343194002.375 3.749877266854425e+26

# exact result: 10775411722410520324.9 >>> try_int_mul(187295, 57531763914736.22) 10775411722410520091 >>> 187295 * 57531763914736.22 1.077541172241052e+19

pycommons.math.int_math.try_int_sqrt(value)[source]

Try to compute the square root of a potentially large integer.

Parameters:

value (int) – the value

Return type:

int | float

Returns:

the square root

Raises:
>>> try_int_sqrt(0)
0
>>> try_int_sqrt(1)
1
>>> try_int_sqrt(2)
1.4142135623730951
>>> try_int_sqrt(3)
1.7320508075688772
>>> try_int_sqrt(4)
2
>>> try_int_sqrt(5)
2.23606797749979
>>> try_int_sqrt(6)
2.449489742783178
>>> try_int_sqrt(7)
2.6457513110645907
>>> try_int_sqrt(8)
2.8284271247461903
>>> try_int_sqrt(9)
3

# exact result: 67108864.0000000074505805969238277 >>> try_int_sqrt(4503599627370497) 67108864 >>> 67108864 * 67108864 4503599627370496 >>> sqrt(4503599627370497) 67108864.0 >>> sqrt(4503599627370497) * sqrt(4503599627370497) 4503599627370496.0

# exact result: 1592262918131443.14115595358963 >>> try_int_sqrt(2535301200456458802993406410753) 1592262918131443.2 >>> sqrt(2535301200456458802993406410753) 1592262918131443.2

# exact result: 6369051672525772.564623814 >>> try_int_sqrt(40564819207303340847894502572033) 6369051672525773 >>> sqrt(40564819207303340847894502572033) 6369051672525773.0

# exact result: 50952413380206180.51699051486817387 >>> try_int_sqrt(2596148429267413814265248164610049) 50952413380206181 >>> sqrt(2596148429267413814265248164610049) 5.0952413380206184e+16

# exact result: 47695509376267.99690952215843525 >>> try_int_sqrt(2274861614661668407597778085) 47695509376267.99 >>> sqrt(2274861614661668407597778085) 47695509376267.99

# exact result: 9067560306493833.1123015448971368313360 >>> try_int_sqrt(82220649911902536690031728766315) 9067560306493833 >>> sqrt(82220649911902536690031728766315) 9067560306493832.0

>>> try_int_sqrt(1156)
34
>>> 34 * 34
1156
>>> sqrt(1156)
34.0
>>> 34.0 * 34.0
1156.0
>>> try_int_sqrt(1005)
31.701734968294716
>>> 31.701734968294716 * 31.701734968294716
1005.0
>>> sqrt(1005)
31.701734968294716
>>> 31.701734968294716 * 31.701734968294716
1005.0

exact result: 109836762562089755439710412785302291476310964802292886550311415346968690934362496833960954250583272879636740982263693728593951807995466301001184452657840914432 >>> try_int_sqrt(int(“12064114410120881697684249086315471354100504503497011563593230129923244688987454586741947156276531487416450850028801674329627080999958126358211839195533902044386710183415792069701368078118158360793576698212191168580174892152827542937880954483101341506291035205862448784848059094859987648259778470316291228729945882624”)) 109836762562089755439710412785302291476310964802292886550311415346968690934362496833960954250583272879636740982263693728593951807995466301001184452657840914432

# exact result: 112519976.73369080909552361 >>> try_int_sqrt(12660745164150321) 112519976.73369081 >>> 112519976.73369081 * 112519976.73369081 1.2660745164150322e+16 >>> sqrt(12660745164150321) 112519976.7336908 >>> 112519976.7336908 * 112519976.7336908 1.2660745164150318e+16

>>> try_int_sqrt(12369445361672285)
111218008.26157734
>>> sqrt(12369445361672285)
111218008.26157734

# exact result: 94906265.624251558157461955425 >>> try_int_sqrt(9007199254740993) 94906265.62425156 >>> 94906265.62425156 * 94906265.62425156 9007199254740994.0 >>> sqrt(9007199254740993) 94906265.62425156 >>> 94906265.62425156 * 94906265.62425156 9007199254740994.0

# exact result: 126969687.206733737782866 >>> try_int_sqrt(16121301469375805) 126969687.20673373 >>> 126969687.20673373 * 126969687.20673373 1.6121301469375804e+16 >>> sqrt(16121301469375805) 126969687.20673373 >>> 126969687.20673373 * 126969687.20673373 1.6121301469375804e+16

# exact result: 94906265.6242515686941740831 # here we are off a bit! >>> try_int_sqrt(9007199254740995) 94906265.62425156 >>> 94906265.62425156 * 94906265.62425156 9007199254740994.0 >>> sqrt(9007199254740995) 94906265.62425157 >>> 94906265.62425157 * 94906265.62425157 9007199254740996.0

# exact result: 102406758.28296330267545316 >>> try_int_sqrt(10487144142025273) 102406758.2829633 >>> 102406758.2829633 * 102406758.2829633 1.0487144142025274e+16 >>> sqrt(10487144142025273) 102406758.28296329 >>> 102406758.28296329 * 102406758.28296329 1.048714414202527e+16

# exact result: 101168874.5492688823358 >>> try_int_sqrt(10235141177565705) 101168874.54926889 >>> 101168874.54926889 * 101168874.54926889 1.0235141177565706e+16 >>> sqrt(10235141177565705) 101168874.54926887 >>> 101168874.54926887 * 101168874.54926887 1.0235141177565702e+16

# exact result: 123961449.976073299398431984 >>> try_int_sqrt(15366441080170523) 123961449.9760733 >>> 123961449.9760733 * 123961449.9760733 1.5366441080170522e+16 >>> sqrt(15366441080170523) 123961449.97607331 >>> 123961449.97607331 * 123961449.97607331 1.5366441080170526e+16

# exact result: 4760418939079673.01527272985 >>> try_int_sqrt(22661588475548439582669426672241) 4760418939079673 >>> 4760418939079673 * 4760418939079673 22661588475548439437260241786929 >>> sqrt(22661588475548439582669426672241) 4760418939079673.0 >>> 4760418939079673.0 * 4760418939079673.0 2.266158847554844e+31

# exact result: 5712179292532910.79362200453777547 >>> try_int_sqrt(32628992270041785263905793906381) 5712179292532911 >>> 5712179292532911 * 5712179292532911 32628992270041787621642018133921 >>> sqrt(32628992270041785263905793906381) 5712179292532911.0 >>> 5712179292532911.0 * 5712179292532911.0 3.2628992270041787e+31

>>> try:
...     try_int_sqrt(-1)
... except ValueError as ve:
...     print(ve)
Compute the root of -1 ... really?
>>> try:
...     try_int_sqrt(1.0)
... except TypeError as te:
...     print(te)
value should be an instance of int but is float, namely 1.0.

pycommons.math.primes module

Tools for working with prime numbers.

pycommons.math.primes.primes(maximum=4294967296)[source]

Provide a sequence of prime numbers.

This function is a generator that returns the prime numbers in their natural order starting at 2. It will return numbers at most up to the given maximum value. For this purpose, it iteratively builds something like the Sieve of Eratosthenes.

Parameters:

maximum (int, default: 4294967296) – the maximum number to consider

Return type:

Generator[int, None, None]

Returns:

the prime numbers

>>> list(primes(-1))
[]
>>> list(primes(0))
[]
>>> list(primes(1))
[]
>>> list(primes(2))
[2]
>>> list(primes(3))
[2, 3]
>>> list(primes(4))
[2, 3]
>>> list(primes(5))
[2, 3, 5]
>>> list(primes(6))
[2, 3, 5]
>>> list(primes(7))
[2, 3, 5, 7]
>>> list(primes(8))
[2, 3, 5, 7]
>>> list(primes(9))
[2, 3, 5, 7]
>>> list(primes(10))
[2, 3, 5, 7]
>>> list(primes(11))
[2, 3, 5, 7, 11]
>>> list(primes(12))
[2, 3, 5, 7, 11]
>>> list(primes(13))
[2, 3, 5, 7, 11, 13]
>>> list(primes(14))
[2, 3, 5, 7, 11, 13]
>>> list(primes(15))
[2, 3, 5, 7, 11, 13]
>>> list(primes(16))
[2, 3, 5, 7, 11, 13]
>>> list(primes(17))
[2, 3, 5, 7, 11, 13, 17]
>>> list(primes(18))
[2, 3, 5, 7, 11, 13, 17]
>>> list(primes(19))
[2, 3, 5, 7, 11, 13, 17, 19]
>>> list(primes(20))
[2, 3, 5, 7, 11, 13, 17, 19]
>>> list(primes(199))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]
>>> list(primes(200))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]
>>> list(primes(201))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]
>>> list(primes(1000))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
>>> try:
...     for t in primes(1.0):
...         pass
... except TypeError as te:
...     print(te)
maximum should be an instance of int but is float, namely 1.0.

pycommons.math.rank module

Some tools for ranking data.

class pycommons.math.rank.K

the type of the key to use during ranking

alias of TypeVar(‘K’)

class pycommons.math.rank.R

the rank type: must either be int, float, or a union of both

alias of TypeVar(‘R’, int, float, int | float)

class pycommons.math.rank.T

the type of the element to sort during ranking

alias of TypeVar(‘T’)

class pycommons.math.rank.X

the output type var

alias of TypeVar(‘X’)

pycommons.math.rank.rank(source, key=<function <lambda>>, output=<function <lambda>>, rank_join=<function <lambda>>, rank_offset=0)[source]

Rank the elements in a data source based on a given key function.

The default behavior of this function is to basically sort the data from source and return tuples with the rank and the data element in a list. The result list is sorted by the keys of the object.

By default, ranks start at 0 and increase in steps of 2. The ranks of objects that would have the same rank are resolved by averaging their ranks. This is why we increment ranks in steps of 2: This way, the mean of two ranks is always an integer: >>> rank([3, 6, 6, 12]) [(0, 3), (3, 6), (3, 6), (6, 12)]

This averaging can be modified by providing a rank_join function that computes a joint rank for objects as well as a rank_offset: >>> rank([3, 6, 6, 12], rank_join=lambda a, b: 0.5 * (a + b)) [(0.0, 3), (1.5, 6), (1.5, 6), (3.0, 12)]

>>> rank([3, 6, 6, 12], rank_join=min, rank_offset=1)
[(1, 3), (2, 6), (2, 6), (4, 12)]
>>> rank([3, 6, 6, 12], rank_join=max, rank_offset=1)
[(1, 3), (3, 6), (3, 6), (4, 12)]

However, the result of rank_offset + rank_join(a, b) must always be either an int or a float and also always finite and never negative, for any two non-negative integers a and b.

The key function must compute a key for each element of source which can be used for sorting. By default, it returns the element itself. But it can be customized. >>> rank((6, 5, 3, 4, 0, 7)) [(0, 0), (2, 3), (4, 4), (6, 5), (8, 6), (10, 7)]

>>> sorted(rank({"a", "c", "X", "y", "x", "xx", "L", "l"}, key=str.lower))
[(0, 'a'), (2, 'c'), (5, 'L'), (5, 'l'), (9, 'X'), (9, 'x'), (12, 'xx'), (14, 'y')]

The output function is used to create the records to be placed in the list returned by this function. Its input are the rank, the object, and its computed key. By default, it creates tuples of the rank and the object obtained from source. You can customize this as well: >>> rank([5, 7, 4, 9, 2, 1]) [(0, 1), (2, 2), (4, 4), (6, 5), (8, 7), (10, 9)]

>>> rank([5, 7, 4, 9, 2, 1], output=lambda rr, oo, kk: f"{rr}:{oo}")
['0:1', '2:2', '4:4', '6:5', '8:7', '10:9']
>>> rank([5, 7, 4, 19, 2, 1], key=str,
...         output=lambda rr, oo, kk: (rr, oo, kk))
[(0, 1, '1'), (2, 19, '19'), (4, 2, '2'), (6, 4, '4'), (8, 5, '5'), (10, 7, '7')]
Parameters:
  • source (Iterable[TypeVar(T)]) – the data source

  • key (Callable[[TypeVar(T)], TypeVar(K)], default: <function <lambda> at 0x7fd58d3c6980>) – a function returning the key for a given object

  • output (Callable[[TypeVar(R, int, float, int | float), TypeVar(T), TypeVar(K)], TypeVar(X)], default: <function <lambda> at 0x7fd58d3c5da0>) – a function creating the output object, receiving the rank, original object, and key as input

  • rank_join (Callable[[int, int], TypeVar(R, int, float, int | float)], default: <function <lambda> at 0x7fd58d3c4360>) – a function for joining a maximum and minimum index of an object to a rank; by default this returns the sum of both

  • rank_offset (int, default: 0) – an offset to be added to the ranks

Return type:

list[TypeVar(X)]

Returns:

a list with the objects generated by the output function, which by default are tuples of rank and object

>>> rank({})
[]
>>> rank([12])
[(0, 12)]
>>> rank([12, 3])
[(0, 3), (2, 12)]
>>> rank([3, 12], rank_offset=2)
[(2, 3), (4, 12)]
>>> rank([12, 12])
[(1, 12), (1, 12)]
>>> rank([12, 12], output=lambda rr, tt, kk: rr)
[1, 1]
>>> rank([-1, 0, 4, 3, 3, 5, 6, 1])
[(0, -1), (2, 0), (4, 1), (7, 3), (7, 3), (10, 4), (12, 5), (14, 6)]
>>> rank([-1, 0, 4, 3, 3, 5, 6, 1], rank_join=lambda a, b: 0.5 * (a + b))
[(0.0, -1), (1.0, 0), (2.0, 1), (3.5, 3), (3.5, 3), (5.0, 4), (6.0, 5), (7.0, 6)]
>>> sorted(rank(("a", "B", "c", "b", "A", "A", "cc"), key=str.casefold))
[(2, 'A'), (2, 'A'), (2, 'a'), (7, 'B'), (7, 'b'), (10, 'c'), (12, 'cc')]
>>> try:
...     rank(1)
... except TypeError as te:
...     print(te)
source should be an instance of typing.Iterable but is int, namely 1.
>>> try:
...     rank([], key=1)
... except TypeError as te:
...     print(te)
key should be a callable but is int, namely 1.
>>> try:
...     rank([], output=1)
... except TypeError as te:
...     print(te)
output should be a callable but is int, namely 1.
>>> try:
...     rank([], rank_join=1)
... except TypeError as te:
...     print(te)
rank_join should be a callable but is int, namely 1.
>>> try:
...     rank([], rank_offset="x")
... except TypeError as te:
...     print(te)
rank_offset should be an instance of any in {float, int} but is str, namely 'x'.
>>> from math import inf, nan
>>> try:
...     rank([], rank_offset=inf)
... except ValueError as ve:
...     print(ve)
rank_offset=inf should be finite
>>> try:
...     rank([], rank_offset=nan)
... except ValueError as ve:
...     print(ve)
rank_offset=nan should be finite
>>> try:
...     rank([1, 2, 3], rank_join=lambda a, b: "x")
... except TypeError as te:
...     print(te)
rank_join(0, 0) should be an instance of any in {float, int} but is str, namely 'x'.
>>> try:
...     rank([1, 2, 3], rank_join=lambda a, b: inf)
... except ValueError as ve:
...     print(ve)
rank inf=rank_join(0, 0) + 0 is not finite and non-negative.
>>> try:
...     rank([1, 2, 3], rank_join=lambda a, b: nan)
... except ValueError as ve:
...     print(ve)
rank nan=rank_join(0, 0) + 0 is not finite and non-negative.

pycommons.math.sample_statistics module

A simple and immutable basic statistics record.

class pycommons.math.sample_statistics.CsvReader(columns)[source]

Bases: object

A csv parser for sample statistics.

>>> from pycommons.io.csv import csv_read
>>> csv = ["n;min;mean;med;geom;max;sd",
...        "3;2;3;4;3;10;5", "6;2;;;;;0", "1;;;2;;;", "3;;;;;0;",
...        "4;5;12;32;11;33;7"]
>>> for p in csv_read(csv, CsvReader, CsvReader.parse_row):
...     print(p)
3;2;4;3;3;10;5
6;2;2;2;2;2;0
1;2;2;2;2;2;None
3;0;0;0;None;0;0
4;5;32;12;11;33;7
>>> csv = ["value", "1", "3", "0", "-5", "7"]
>>> for p in csv_read(csv, CsvReader, CsvReader.parse_row):
...     print(p)
1;1;1;1;1;1;None
1;3;3;3;3;3;None
1;0;0;0;None;0;None
1;-5;-5;-5;None;-5;None
1;7;7;7;7;7;None
>>> csv = ["n;m;sd", "1;3;", "3;5;0"]
>>> for p in csv_read(csv, CsvReader, CsvReader.parse_row):
...     print(p)
1;3;3;3;3;3;None
3;5;5;5;5;5;0
>>> csv = ["n;m", "1;3", "3;5"]
>>> for p in csv_read(csv, CsvReader, CsvReader.parse_row):
...     print(p)
1;3;3;3;3;3;None
3;5;5;5;5;5;0
idx_n: Final[int | None]

the index of the number of elements

parse_optional_row(data)[source]

Parse a row of data that may be empty.

Parameters:

data (list[str] | None) – the row of data that may be empty

Return type:

SampleStatistics | None

Returns:

the sample statistic, if the row contains data, else None

>>> print(CsvReader.parse_optional_row(None, ["1"]))
None
>>> print(CsvReader.parse_optional_row(CsvReader({"v": 0}), ["1"]))
1;1;1;1;1;1;None
>>> print(CsvReader.parse_optional_row(CsvReader({"v": 0}), [""]))
None
parse_row(data)[source]

Parse a row of data.

Parameters:

data (list[str]) – the data row

Return type:

SampleStatistics

Returns:

the sample statistics

class pycommons.math.sample_statistics.CsvWriter(scope=None, n_not_needed=False, what_short=None, what_long=None)[source]

Bases: object

A class for CSV writing of SampleStatistics.

get_column_titles()[source]

Get the column titles.

Return type:

Iterable[str]

Returns:

the column titles

>>> try:
...     list(CsvWriter().get_column_titles())
... except ValueError as ve:
...     print(ve)
SampleStatistics CsvWriter has not been set up.

Get the bottom footer comments.

Return type:

Optional[Iterable[str]]

Returns:

an iterator with the bottom comments

>>> for p in CsvWriter.get_footer_bottom_comments(None):
...     print(p[:70])
This CSV output has been created using the versatile CSV API of pycomm
Sample statistics were computed using pycommons.math.sample_statistics
You can find pycommons at https://thomasweise.github.io/pycommons.

Get any possible footer comments.

Return type:

Iterable[str]

Returns:

the footer comments

get_header_comments()[source]

Get any possible header comments.

Return type:

Iterable[str]

Returns:

the iterable of header comments

get_optional_row(data, n=None)[source]

Attach an empty row of the correct shape to the output.

This function may be needed in cases where the statistics are part of other records that sometimes do not contain the record.

Parameters:
Return type:

Iterable[str]

Returns:

the optional row data

>>> try:
...     list(CsvWriter().get_optional_row("x"))
... except TypeError as te:
...     print(str(te)[:53])
data should be an instance of any in {None, float, in
get_row(data)[source]

Render a single sample statistics to a CSV row.

Parameters:

data (SampleStatistics) – the data sample statistics

Return type:

Iterable[str]

Returns:

the row iterator

n_not_needed: Final[bool]

is the n-column needed

setup(data)[source]

Set up this csv writer based on existing data.

Parameters:

data (Iterable[SampleStatistics]) – the data to setup with

Return type:

CsvWriter

Returns:

this writer

>>> a = CsvWriter()
>>> try:
...     a.setup([])
... except ValueError as ve:
...     print(ve)
SampleStatistics CsvWriter did not see any data.
>>> try:
...     a.setup([])
... except ValueError as ve:
...     print(ve)
SampleStatistics CsvWriter has already been set up.
>>> try:
...     CsvWriter().setup([1])
... except TypeError as te:
...     print(str(te)[:60])
data[i] should be an instance of pycommons.math.sample_stati
pycommons.math.sample_statistics.KEY_MAXIMUM: Final[str] = 'max'

The maximum value key.

pycommons.math.sample_statistics.KEY_MEAN_ARITH: Final[str] = 'mean'

The arithmetic mean value key.

pycommons.math.sample_statistics.KEY_MEAN_GEOM: Final[str] = 'geom'

The geometric mean value key.

pycommons.math.sample_statistics.KEY_MEDIAN: Final[str] = 'med'

The median value key.

pycommons.math.sample_statistics.KEY_MINIMUM: Final[str] = 'min'

The minimum value key.

pycommons.math.sample_statistics.KEY_N: Final[str] = 'n'

The key for n

pycommons.math.sample_statistics.KEY_STDDEV: Final[str] = 'sd'

The standard deviation value key.

pycommons.math.sample_statistics.KEY_VALUE: Final[str] = 'value'

The single value

class pycommons.math.sample_statistics.SampleStatistics(n, minimum, median, mean_arith, mean_geom, maximum, stddev)[source]

Bases: object

An immutable record with sample statistics of one quantity.

compact(needs_n=True)[source]

Try to represent this object as single number, if possible.

Parameters:

needs_n (bool, default: True) – if this is True, the default, then the object is only turned into a single number if alsp n==1. Otherwise, n is ignored

Return type:

int | float | SampleStatistics

Returns:

an integer or float if this objects minimum equals its maximum, the object itself otherwise

>>> s = from_single_value(10, 1)
>>> s.compact() == 10
True
>>> s.compact() == s.compact(True)
True
>>> s = from_single_value(10, 2)
>>> s.compact() is s
True
>>> s.compact() == s.compact(True)
True
>>> s = from_single_value(10, 2)
>>> s.compact(False) == 10
True
>>> s = SampleStatistics(2, 1, 2, 4, 3, 5, 3)
>>> s.compact() is s
True
>>> s = SampleStatistics(2, 1, 2, 4, 3, 5, 3)
>>> s.compact(False) is s
True
>>> try:
...     s.compact(1)
... except TypeError as te:
...     print(te)
needs_n should be an instance of bool but is int, namely 1.
>>> try:
...     s.compact(None)
... except TypeError as te:
...     print(te)
needs_n should be an instance of bool but is None.
get_maximum()[source]

Get the maximum of all the samples.

Return type:

int | float

Returns:

the maximum of all the samples

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_maximum()
7
>>> try:
...     SampleStatistics.get_maximum(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_mean_arith()[source]

Get the arithmetic mean (mean_arith) of all the samples.

Return type:

int | float

Returns:

the arithmetic mean (mean_arith) of all the samples.

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_mean_arith()
6
>>> try:
...     SampleStatistics.get_mean_arith(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_mean_geom()[source]

Get the geometric mean (mean_geom) of all the samples.

Return type:

int | float | None

Returns:

the geometric mean (mean_geom) of all the samples, None if the geometric mean is not defined.

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_mean_geom()
4
>>> try:
...     SampleStatistics.get_mean_geom(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_median()[source]

Get the median of all the samples.

Return type:

int | float

Returns:

the median of all the samples.

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_median()
5
>>> try:
...     SampleStatistics.get_median(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_minimum()[source]

Get the minimum of all the samples.

Return type:

int | float

Returns:

the minimum of all the samples

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_minimum()
3
>>> try:
...     SampleStatistics.get_minimum(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_n()[source]

Get the number n of samples.

Return type:

int

Returns:

the number n of samples.

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_n()
5
>>> try:
...     SampleStatistics.get_n(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
get_stddev()[source]

Get the standard deviation mean (stddev) of all the samples.

Return type:

int | float | None

Returns:

the standard deviation (stddev) of all the samples, None if the standard deviation is not defined, i.e., if there is only a single sample

Raises:

TypeError – if an object of the wrong type is passed in as self

>>> SampleStatistics(5, 3, 5, 6, 4, 7, 2).get_stddev()
2
>>> try:
...     SampleStatistics.get_stddev(None)
... except TypeError as te:
...     print(str(te)[:20])
self should be an in
max_mean()[source]

Obtain the largest of the three mean values.

Return type:

int | float

Returns:

the largest of mean_arith, mean_geom, and median

>>> SampleStatistics(1, 0, 0.0, 0, None, 0.0, None).max_mean()
0
>>> SampleStatistics(2, 1, 2, 4.0, 3, 6, 0.2).max_mean()
4
>>> SampleStatistics(2, 1, 3.2, 4.0, 3, 6, 0.2).max_mean()
4
>>> SampleStatistics(2, 1, 5.2, 4.0, 3, 6, 0.2).max_mean()
5.2
maximum: int | float

The maximum, i.e., the value of the largest among the n data samples.

mean_arith: int | float

The arithmetic mean value, i.e., the sum of the n data samples divided by n.

mean_geom: int | float | None

The geometric mean value, if defined. This is the n-th root of the product of all data samples. This value will be None if there was any sample which is not greater than 0.

median: int | float

The median, i.e., the value in the middle of the sorted list of n data samples.

min_mean()[source]

Obtain the smallest of the three mean values.

Return type:

int | float

Returns:

the smallest of mean_arith, mean_geom, and median

>>> SampleStatistics(1, 0, 0.0, 0, None, 0.0, None).min_mean()
0
>>> SampleStatistics(2, 1, 2, 4.0, 3, 6, 0.2).min_mean()
2
>>> SampleStatistics(2, 1, 3.2, 4.0, 3, 6, 0.2).min_mean()
3
>>> SampleStatistics(2, 1, 5.2, 4.0, 3, 6, 0.2).min_mean()
3
minimum: int | float

The minimum, i.e., the value of the smallest among the n data samples.

n: int

The number of data samples over which the statistics were computed.

stddev: int | float | None

The standard deviation, if defined. This value will be None if there was only a single sample.

pycommons.math.sample_statistics.from_samples(source)[source]

Create a statistics object from an iterable of integers or floats.

As bottom line, this function will forward computations to the statistics routines that ship with Python if nothing else works. However, sometimes, something else may work: In particular, if the data consists of only integers. In this case, it just might be possible to compute the statistics very accurately with integer precision, where possible.

Let’s say we have a sequence of pure integers. We can compute the arithmetic mean by

Parameters:

source (Iterable[int | float]) – the source

Return type:

SampleStatistics

Returns:

a statistics representing the statistics over source

>>> s = from_samples([0.0])
>>> s.n
1
>>> s.minimum
0
>>> s.maximum
0
>>> print(s.mean_geom)
None
>>> s.median
0
>>> print(s.stddev)
None
>>> s = from_samples([1.0])
>>> s.n
1
>>> s.minimum
1
>>> s.maximum
1
>>> print(s.mean_geom)
1
>>> s.median
1
>>> print(s.stddev)
None
>>> s = from_samples([1.0, 1])
>>> s.n
2
>>> s.minimum
1
>>> s.maximum
1
>>> print(s.mean_geom)
1
>>> s.median
1
>>> print(s.stddev)
0
>>> s = from_samples([0, 0.0])
>>> s.n
2
>>> s.minimum
0
>>> s.maximum
0
>>> print(s.mean_geom)
None
>>> s.median
0
>>> print(s.stddev)
0
>>> dd = [1.5, 2.5]
>>> s = from_samples(dd)
>>> s.n
2
>>> s.minimum
1.5
>>> s.maximum
2.5
>>> print(s.mean_geom)
1.9364916731037085
>>> stat_geomean(dd)
1.9364916731037085
>>> s.median
2
>>> print(s.stddev)
0.7071067811865476
>>> stat_stddev(dd)
0.7071067811865476
>>> dd = [1.0, 2.0]
>>> s = from_samples(dd)
>>> s.n
2
>>> s.minimum
1
>>> s.maximum
2
>>> print(s.mean_geom)
1.4142135623730951
>>> (1 * 2) ** 0.5
1.4142135623730951
>>> stat_geomean(dd)
1.414213562373095
>>> s.median
1.5
>>> print(s.stddev)
0.7071067811865476
>>> stat_stddev(dd)
0.7071067811865476
>>> dd = [1.0, 2.0, 3.0]
>>> s = from_samples(dd)
>>> s.n
3
>>> s.minimum
1
>>> s.maximum
3
>>> print(s.mean_geom)
1.8171205928321397
>>> (1 * 2 * 3) ** (1 / 3)
1.8171205928321397
>>> stat_geomean(dd)
1.8171205928321397
>>> s.median
2
>>> print(s.stddev)
1
>>> stat_stddev(dd)
1.0
>>> dd = [1.0, 0, 3.0]
>>> s = from_samples(dd)
>>> s.n
3
>>> s.minimum
0
>>> s.maximum
3
>>> print(s.mean_geom)
None
>>> s.median
1
>>> print(s.stddev)
1.5275252316519468
>>> stat_stddev(dd)
1.5275252316519468
>>> dd = [1.0, -2, 3.0]
>>> s = from_samples(dd)
>>> s.n
3
>>> s.minimum
-2
>>> s.maximum
3
>>> print(s.mean_geom)
None
>>> s.median
1
>>> print(s.stddev)
2.516611478423583
>>> stat_stddev(dd)
2.516611478423583
>>> dd = [1e5, 2e7, 3e9]
>>> s = from_samples(dd)
>>> s.n
3
>>> s.minimum
100000
>>> s.maximum
3000000000
>>> print(s.mean_geom)
18171205.928321395
>>> (100000 * 20000000 * 3000000000) ** (1 / 3)
18171205.92832138
>>> 100000 * (((100000 // 100000) * (20000000 // 100000) * (
...     3000000000 // 100000)) ** (1 / 3))
18171205.92832139
>>> print(s.mean_geom ** 3)
5.999999999999999e+21
>>> print(18171205.92832139 ** 3)
5.999999999999995e+21
>>> s.median
20000000
>>> print(s.stddev)
1726277112.7487035
>>> stat_stddev(dd)
1726277112.7487035
>>> dd = [3.3, 2.5, 3.7, 4.9]
>>> s = from_samples(dd)
>>> s.n
4
>>> s.minimum
2.5
>>> s.maximum
4.9
>>> print(s.mean_geom)
3.497139351921697
>>> (3.3 * 2.5 * 3.7 * 4.9) ** 0.25
3.497139351921697
>>> s.median
3.5
>>> print(s.stddev)
1.0000000000000002
>>> stat_stddev(dd)
1.0000000000000002
>>> dd = [3, 1, 2, 5]
>>> s = from_samples(dd)
>>> print(s.minimum)
1
>>> print(s.maximum)
5
>>> print(s.mean_arith)
2.75
>>> print(s.median)
2.5
>>> print(f"{s.mean_geom:.4f}")
2.3403
>>> print(f"{s.min_mean():.4f}")
2.3403
>>> print(f"{s.max_mean()}")
2.75
>>> dd = [8, 8, 8, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13,
...       13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16]
>>> s = from_samples(dd)
>>> print(s.minimum)
8
>>> print(s.maximum)
16
>>> print(s.mean_arith)
12.5
>>> print(s.median)
13
>>> print(s.mean_geom)
12.19715026502289
>>> stat_geomean(dd)
12.19715026502289
>>> print(s.stddev)
2.673602092336881
>>> stat_stddev(dd)
2.673602092336881
>>> dd = [3, 4, 7, 14, 15, 16, 26, 28, 29, 30, 31, 31]
>>> s = from_samples(dd)
>>> print(s.minimum)
3
>>> print(s.maximum)
31
>>> print(s.mean_arith)
19.5
>>> print(s.median)
21
>>> print(s.mean_geom)
15.354984483655892
>>> stat_geomean(dd)
15.354984483655894
>>> k = 1
>>> for i in dd:
...     k *= i
>>> k
171787904870400
>>> len(dd)
12
>>> k ** (1 / 12)
15.354984483655889
>>> 15.354984483655889 ** 12
171787904870399.62
>>> 15.354984483655894 ** 12
171787904870400.34
>>> 15.354984483655892 ** 12
171787904870400.1
>>> print(s.stddev)
10.917042556563485
>>> print(str(stat_stddev(dd))[:-1])
10.91704255656348
>>> dd = [375977836981734264856247621159545315,
...       1041417453269301410322718941408784761,
...       2109650311556162106262064987699051941]
>>> s = from_samples(dd)
>>> print(s.minimum)
375977836981734264856247621159545315
>>> print(s.maximum)
2109650311556162106262064987699051941
>>> print(s.mean_arith)
1175681867269065927147010516755794006
>>> stat_mean(dd)
1.1756818672690659e+36
>>> print(s.median)
1041417453269301410322718941408784761
>>> print(s.mean_geom)
9.382801392765291e+35
>>> stat_geomean(dd)
9.38280139276522e+35
>>> str(dd[0] * dd[1] * dd[2])[:60]
'826033329443972563356247815302467930409182372405786485790679'
>>> str(int(9.382801392765291e+35) ** 3)[:60]
'826033329443972374842763874805993468673735440486439147266106'
>>> str(int(9.38280139276522e+35) ** 3)[:60]
'826033329443953666416831847378532327244986484162191539691938'
>>> print(s.stddev)
874600058269081159245960567663054887
>>> stat_stddev(dd)
8.746000582690812e+35
>>> dd = [104275295274308290135253194482044160663473778025704,
...       436826861307375084714000787588311944456580437896461,
...       482178404791292289021955619498303854464057392180997,
...       521745351662201002493923306143082542601267608373030,
...       676289718505789968602970820038005797309334755525626]
>>> s = from_samples(dd)
>>> print(s.minimum)
104275295274308290135253194482044160663473778025704
>>> print(s.maximum)
676289718505789968602970820038005797309334755525626
>>> print(s.mean_arith)
444263126308193326993620745549949659898942794400364
>>> stat_mean(dd)
4.442631263081933e+50
>>> print(s.median)
482178404791292289021955619498303854464057392180997
>>> print(s.mean_geom)
3.783188481668667e+50
>>> stat_geomean(dd)
3.78318848166862e+50
>>> print(s.stddev)
210311926886813737006941586539087921260462032505870
>>> stat_stddev(dd)
2.1031192688681374e+50
>>> dd = [4, 5, 5, 6, 6, 6, 6, 6, 8, 8]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
5.884283961687533
>>> print(stat_geomean(dd))
5.884283961687533
>>> dd = [4, 4, 4, 5, 5, 8]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
4.836542350243914
>>> print(stat_geomean(dd))
4.8365423502439135
>>> dd = [2, 8, 11, 17, 26, 30, 32]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
13.327348017053906
>>> print(stat_geomean(dd))
13.327348017053906
>>> dd = [2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
3.4710522375429465
>>> print(stat_geomean(dd))
3.471052237542947
>>> dd = [3, 4, 4, 5, 6, 8, 8, 8, 8]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
5.653305998922543
>>> print(stat_geomean(dd))
5.653305998922543
>>> dd = [16, 17, 19, 20, 20, 21, 22, 23, 24, 24, 25, 26, 29, 31,
...       31, 31, 32, 32, 32]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
24.419566831650357
>>> print(stat_geomean(dd))
24.41956683165036
>>> dd = [66, 68, 69, 70, 72, 73, 73, 79, 81, 87, 94, 99, 100, 102, 103,
...       112, 118, 119, 123, 123]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
89.45680043258344
>>> print(stat_geomean(dd))
89.45680043258346
>>> dd = [44, 63, 63, 68, 68, 68, 70, 74, 74, 80, 95, 108, 110, 128]
>>> s = from_samples(dd)
>>> print(s.mean_geom)
76.6864641736076
>>> print(stat_geomean(dd))
76.68646417360763
>>> try:
...     from_samples(None)
... except TypeError as te:
...     print(te)
source should be an instance of typing.Iterable but is None.
>>> from_samples((int("34321354472872354942019350661824880247844254573312782740274335009242834156372188002285290074477536810411720141041"), int("45431788008354832695126092828840751261426775316001998077250558561959304806690567285991174956892786401583087254156"), int("35473203294104466229269097724582630304968924904656920211268628173495602053843032960943121516556362641127137000879"))).mean_arith
38408781925110551288804847071749420604746651597990567009597840581565913672301929416406528849308895284373981465359
>>> try:
...     from_samples(1)
... except TypeError as te:
...     print(te)
source should be an instance of typing.Iterable but is int, namely 1.
>>> try:
...     from_samples([])
... except ValueError as ve:
...     print(ve)
Data source cannot be empty.
pycommons.math.sample_statistics.from_single_value(value, n=1)[source]

Create a sample statistics from a single number.

Parameters:
  • value (int | float | SampleStatistics) – the single value

  • n (int, default: 1) – the number of samples, i.e., the number of times this value occurred

Return type:

SampleStatistics

Returns:

the sample statistics

>>> s = from_single_value(10, 2)
>>> print(s.stddev)
0
>>> s.minimum == s.maximum == s.mean_arith == s.mean_geom \
...     == s.median == 10
True
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(10, 1)
>>> print(s.stddev)
None
>>> s.minimum == s.maximum == s.mean_arith == s.mean_geom \
...     == s.median == 10
True
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(-10, 2)
>>> print(s.stddev)
0
>>> s.minimum == s.maximum == s.mean_arith == s.median == -10
True
>>> print(s.mean_geom)
None
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(-10, 1)
>>> print(s.stddev)
None
>>> s.minimum == s.maximum == s.mean_arith == s.median == -10
True
>>> print(s.mean_geom)
None
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(10.5, 2)
>>> print(s.stddev)
0
>>> s.minimum == s.maximum == s.mean_arith == s.mean_geom \
...     == s.median == 10.5
True
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(10.5, 1)
>>> print(s.stddev)
None
>>> s.minimum == s.maximum == s.mean_arith == s.mean_geom \
...     == s.median == 10.5
True
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(-10.5, 2)
>>> print(s.stddev)
0
>>> s.minimum == s.maximum == s.mean_arith == s.median == -10.5
True
>>> print(s.mean_geom)
None
>>> s is from_single_value(s, s.n)
True
>>> s = from_single_value(-10.5, 1)
>>> print(s.stddev)
None
>>> s.minimum == s.maximum == s.mean_arith == s.median == -10.5
True
>>> print(s.mean_geom)
None
>>> s is from_single_value(s, s.n)
True
>>> try:
...     from_single_value(None)
... except TypeError as te:
...     print(str(te)[:20])
value should be an i
>>> try:
...     from_single_value("a")
... except TypeError as te:
...     print(str(te)[:20])
value should be an i
>>> try:
...     from_single_value(1, None)
... except TypeError as te:
...     print(str(te)[:20])
n should be an insta
>>> try:
...     from_single_value(1, "a")
... except TypeError as te:
...     print(str(te)[:20])
n should be an insta
>>> try:
...     from_single_value(s, 12)
... except ValueError as ve:
...     print(str(ve)[:20])
Incompatible numbers
>>> try:
...     from_single_value(inf)
... except ValueError as ve:
...     print(str(ve)[:20])
value=inf is not fin
pycommons.math.sample_statistics.getter(dimension)[source]

Get a function returning the dimension from SampleStatistics.

Parameters:

dimension (str) – the dimension

Return type:

Callable[[SampleStatistics], int | float | None]

Returns:

a Callable that returns the value corresponding to the dimension

Raises:
>>> getter(KEY_N) is SampleStatistics.get_n
True
>>> getter(KEY_MINIMUM) is SampleStatistics.get_minimum
True
>>> getter(KEY_MEAN_ARITH) is SampleStatistics.get_mean_arith
True
>>> getter(KEY_MEDIAN) is SampleStatistics.get_median
True
>>> getter(KEY_MEAN_GEOM) is SampleStatistics.get_mean_geom
True
>>> getter(KEY_MAXIMUM) is SampleStatistics.get_maximum
True
>>> getter(KEY_STDDEV) is SampleStatistics.get_stddev
True
>>> s = SampleStatistics(5, 3, 5, 6, 4, 7, 2)
>>> getter(KEY_N)(s)
5
>>> getter(KEY_MINIMUM)(s)
3
>>> getter(KEY_MEAN_ARITH)(s)
6
>>> getter(KEY_MEDIAN)(s)
5
>>> getter(KEY_MEAN_GEOM)(s)
4
>>> getter(KEY_MAXIMUM)(s)
7
>>> getter(KEY_STDDEV)(s)
2
>>> try:
...     getter(None)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'NoneType' object
>>> try:
...     getter(1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     getter("hello")
... except ValueError as ve:
...     print(ve)
Unknown SampleStatistics dimension 'hello'.