Large integer modulo division is not very convincing - python

Look at these:
>>>from mpmath import mp
>>> 20988936657440586486151264256610222593863921 % 2623617082180073274358906876623916797788160
291280009243618888211558641
>>> 20988936657440586486151264256610222593863921 % 5247234164360146548717813753247833595576320
291280009243618888211558641 <<<HOW CAN THIS BE THE SAME ANSWER AS ABOVE?
>>> mp.fdiv(20988936657440586486151264256610222593863921, 5247234164360146548717813753247833595576320)
mpf('4.00000000000000005551115123125782779)
>>> mp.fdiv(20988936657440586486151264256610222593863921, 2623617082180073274358906876623916797788160)
mpf('8.00000000000000011102230246251565558)
I am trying to write a program that returns true if a large number is prime.
As you probably already know, python has its limits. Not just with floating point numbers but also with large numbers above a decillion. If my Python 3.7 (64-bit) can support large integers up to:
import sys
int(sys.float_info.max)
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
...then why can I not do a simple modulo on the numbers above and not get inconsistencies? Can anyone refer me to some other tool to help me or is there something I'm just missing?

Related

Is there a way to have fractions with roots?

Is there a way to have fractions (in python) with roots? When I write Fraction(np.sqrt(2), 2), it gives me 1/2, because Fraction takes ints as arguments. I want to have square root of 2 divided by 2, and keep the 2 under the root as to not lose precision while calculating.
Edit: I am using the package "fraction". I couldn't find "fractions" anywhere when I searched for the package to install.
Not entirely certain if the following is what you want, but, here it goes:
from fractions import Fraction as F
import numpy as np
print(F(F(np.sqrt(2)), 2).limit_denominator(max_denominator=100000))
print(5741/8119) # with max_denominator=10000
print(33461/47321)
print(np.sqrt(2)/2)
Will produce:
33461/47321
0.7071067865500678
0.7071067813444348
0.7071067811865476
Update
Irrational to rational conversion cannot possibly preserve precision. No rational fraction can ever be equal to the relevant irrational number. All we can do is get to the closest value!
As a further insight, an enhancement proposal for inclusion of irrational numbers in fractions was rejected.
EDIT
If all you want is to display it mathematically in unicode:
from pylatexenc.latex2text import LatexNodes2Text
# To convert some latex unicode input to actual latex output
in_expr_unicode = r"""$\frac{\sqrt{2}}{2}$"""
out_latex = LatexNodes2Text().latex_to_text(in_expr_unicode)
print(' The math formula: ', out_latex)
which will output:
The math formula: √(2)/2
As a comment suggested, I found sqrt in the sympy package. For example sympy.sqrt(8) produces 2*sqrt(2), so it doesn't just keep the number under the root as not to lose precision, it also lets me make operations with it and simplifies it.

Maximum decimal place in python

I know that python's integer is unbounded, but how many significant digits can a floating point number contain
I think is what you want.
import sys
sys.float_info.max
I get 1.7976931348623157e+308
The docs: https://docs.python.org/3/library/sys.html#sys.float_info
Part 2:
The answer is tricky as several factors may get in the way and the practical use of float in an application is also a limiting factor (what do you want to do?). Rounding and OS may change this, but that is a whole different discussion.
Here is a pedestrian means to get a simple and imperfect answer:
>>> import math
>>> format(math.pi, '.48g')
'3.14159265358979311599796346854418516159057617188'
>>> format(math.pi, '.49g')
'3.141592653589793115997963468544185161590576171875'
>>> format(math.pi, '.50g')
'3.141592653589793115997963468544185161590576171875'
>>> format(math.pi, '.51g')
'3.141592653589793115997963468544185161590576171875'
>>> len(str(141592653589793115997963468544185161590576171875))
48
Some info to look at:
Use of float in various systems: https://press.rebus.community/programmingfundamentals/chapter/floating-point-data-type/
Intro to the standard: https://stackoverflow.com/a/36720298/860715
The standard: https://en.wikipedia.org/wiki/IEEE_754
There are several ways I could see attacking question, but any result would be easy for a comp-sci or serious math person to bust. In PHP I have been burned by OS and float many times. Python is much better, but it still extends a lot of the underlying operating system's operations and that is something that can get unpredictable when pushing the limits.
I hope this helps as any answer provided is sure to be riddled with debate. In the long run you probably need to get something running and want to know what you can use reliably. I hope my proof gets you closer to that conclusion.
python [...] how many significant digits can a floating point number contain
767 is the most (when it uses double-precision, which I think it does for pretty much everyone).
One such number is (253 - 1) / 21074.
Demo:
>>> len(('%.2000f' % ((2**53 - 1) / 2**1074)).strip('0.'))
767
Got it from this article which goes into more detail.
The number in its full beauty (broken into lines for readability:
>>> print('\n'.join(textwrap.wrap(('%.2000f' % ((2**53 - 1) / 2**1074)).rstrip('0'))))
0.00000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000044501477170144022721148195934182639518696
3909270329129604685221944964444404215389103305904781627017582829831782
6079242213740172877389189291055314414815641243486759976282126534658507
1045737627442980259622449029037796981144446145705102663115100318287949
5279596682360399864792509657803421416370138126133331198987655154514403
1526125381326665295130600018491776632866075559583739224098994780755659
4098101021612198814605258742579179000071675999344145086087205681577915
4359230189103349648694206140521828924314457976051636509036065141403772
1744226256159024466852576737244643007551333245007965068671949137768847
8005309963967709758965844137894433796621993967316936280457084866613206
7970177289160800206986794085513437288676754097207572324554347709124613
17493580281734466552734375

Increase Accuracy of float division (python)

I'm writing a bit of code in PyCharm, and I want the division to be much more accurate than it currently is (40-50 numbers instead of about 15). How Can I accomplish this?
Thanks.
Check out the decimal module:
>>> from decimal import *
>>> getcontext().prec = 50
>>> Decimal(1)/Decimal(7)
Decimal('0.14285714285714285714285714285714285714285714285714')
If you're interested in more sophisticated operations than decimal provides, you can also look at libraries like bigfloat, or mpmath (which I use, and like a lot.)

Exponential of very small number in python

I am trying to calculate the exponential of -1200 in python (it's an example, I don't need -1200 in particular but a collection of numbers that are around -1200).
>>> math.exp(-1200)
0.0
It is giving me an underflow; How may I go around this problem?
Thanks for any help :)
In the standard library, you can look at the decimal module:
>>> import decimal
>>> decimal.Decimal(-1200)
Decimal('-1200')
>>> decimal.Decimal(-1200).exp()
Decimal('7.024601888177132554529322758E-522')
If you need more functions than decimal supports, you could look at the library mpmath, which I use and like a lot:
>>> import mpmath
>>> mpmath.exp(-1200)
mpf('7.0246018881771323e-522')
>>> mpmath.mp.dps = 200
>>> mpmath.exp(-1200)
mpf('7.0246018881771325545293227583680003334372949620241053728126200964731446389957280922886658181655138626308272350874157946618434229308939128146439669946631241632494494046687627223476088395986988628688095132e-522')
but if possible, you should see if you can recast your equations to work entirely in the log space.
Try calculating in logarithmic domain as long as possible. I.e. avoid calculating the exact value but keep working with exponents.
exp(-1200) IS a very very small number (just as exp(1200) is a very very big one), so maybe the exact value is not really what you are interested in. If you only need to compare these numbers then logarithmic space should be enough.

Python modulus result is incorrect

I am totally stumped. I was computing the cipher of the number 54 in RSA with the following values:
p=5; q=29; n=145
d=9; e=137
So the number 54 encrypted would be:
54^137 mod 145
or equivalently in python:
import math
math.pow(54,137)%145
My calculator gives me 24, my python statement gives me 54.0. Python is clearly wrong but I have no idea why or how. Try it on your installations of Python. My version is 2.5.1 but I also tried on 2.6.5 with the same incorrect result.
>>> pow(54,137,145)
24
math.pow is floating point. You don't want that. Floating-point values have less than 17 digits of useful precision. The 54**137 has 237 digits.
That's because using the math module is basically just a Python wrapper for the C math library which doesn't have arbitrary precision numbers. That means math.pow(54,137) is calculating 54^137 as a 64-bit floating point number, which means it will not be precise enough to hold all the digits of such a large number. Try this instead to use Python's normal built-in arbitrary precision integers:
>>> (54 ** 137) % 145
24L

Categories

Resources