I am performing calculation in python that results in very large numbers. The smallest of them is 2^10^6, this number is extremely long so I attempted to use format() to convert it to scientific notation. I keep getting an error message stating that the number is too large to convert to a float.
this is the error I keep getting:
print(format(2**10**6, "E"))
OverflowError: int too large to convert to float
I would like to print the result of 2^10^6 in a way that is concise and readable
You calculated 2 raised to the 10th then raised to the 6th power. If your aim is "2 times 10 to the sixth", then 2*10**6 is what you want. In python that can also be expressed by 2E6 where E means "to the 10th power". This is confusing when you are thinking in terms of natural logs and Euler's Number e.
You can also use the decimal.Decimal package if you want to side step decimal to binary float problems. In python, floats expressed in decimal are rounded to the nearest binary float. If you really did want the huge number, Decimal can handle it.
>>> Decimal("2E6")
Decimal('2E+6')
>>> Decimal("2")*10**6
Decimal('2000000')
>>> Decimal("2")**10**6
Decimal('9.900656229295898250697923616E+301029')
For printing, use the "g" format
>>> d = Decimal('2')**10**6
>>> format(d,'g')
'9.900656229295898250697923616e+301029'
>>> format(d,'.6g')
'9.90066e+301029'
>>> "{:g}".format(d)
'9.900656229295898250697923616e+301029'
>>> "{:.6g}".format(d)
'9.90066e+301029'
Related
I had some issues with a piece of code and ended up doing the following command line snippet.This was just an experiment and I didn't store such large values in any variable in the real code(modulo 10**9 +7).
>>> a=1
>>> for i in range(1,101):
... a=a*i
...
>>> b=1
>>> for i in range(1,51):
... b=b*i
...
>>> c=pow(2,50)
>>> a//(b*c)
2725392139750729502980713245400918633290796330545803413734328823443106201171875
>>> a/(b*c)
2.7253921397507295e+78
>>> (a//(b*c))%(10**9 +7)
196932377
>>> (a/(b*c))%(10**9 +7)
45708938.0
>>>
I don't understand why integer divison gives the correct output while floating point divison fails.
Basically I calculated: ( (100!) / ((50!)*(2^50)) ) % (10**9 +7)
Because of precision.
Integers and floats are coded differently. In particular, in python 3, integers can be arbitrarily large - the one you gave, for example, is more than 250 bits large when you convert it to binary. They're stored in a way that can accommodate however large they are.
However, floating-point numbers are constrained to a certain size - usually 64 bits. These 64 bits are divided into a sign (1 bit), mantissa, and exponent - the number of bits in the mantissa limit how precise the number can be. Python's documentation contains a section on this limitation.
So, when you do
(a//(b*c))%(10**9 +7)
you're performing that calculation with integers, which, again, are arbitrarily large. However, when you do this:
(a/(b*c))%(10**9 +7)
you're performing that calculation with a number that only has 18 significant digits - it's already imprecise, and doing more calculations with it only further corrupts the answer.
What you can do to avoid this, if you need to use very large floating-point numbers, is use python's decimal module (which is part of the standard library), which will not have these problems.
The reason is that integers are precise, but floats are limited by the floating point precision: Python2.7 default float precision
I will explain my problem by example:
>>> #In this case, I get unwanted result
>>> k = 20685671025767659927959422028 / 2580360422
>>> k
8.016582043889239e+18
>>> math.floor(k)
8016582043889239040
>>> #I dont want this to happen ^^, let it remain 8.016582043889239e+18
>>> #The following case though, is fine
>>> k2 = 5/6
>>> k2
0.8333333333333334
>>> math.floor(k2)
0
How do I make math.floor not flooring the scientific notated numbers? Is there a rule for which numbers are represented in a scientific notation (I guess it would be a certain boundry).
EDIT:
I first thought that the math.floor function was causing an accuracy loss, but it turns out that the first calculation itself lost the calculation's accuracy, which had me really confused, it can be easily seen here:
>>> 20685671025767659927959422028 / 2580360422
8016582043889239040
>>> 8016582043889239040 * 2580360422
20685671025767659370513274880
>>> 20685671025767659927959422028 - 20685671025767659370513274880
557446147148
>>> 557446147148 / 2580360422
216.0342184739958
>>> ##this is >1, meaning I lost quite a bit of information, and it was not due to the flooring
So now my problem is how to get the actual result of the division. I looked at the following thread:
How to print all digits of a large number in python?
But for some reason I didn't get the same result.
EDIT:
I found a simple solution for the division accuracy problem in here:
How to manage division of huge numbers in Python?
Apparently the // operator returns an int rather then float, which has no size limit apart to the machine's memory.
In Python 3, math.floor returns an integer. Integers are not displayed using scientific notation. Some floats are represented using scientific notation. If you want scientific notation, try converting back to float.
>>> float(math.floor(20685671025767659927959422028 / 2580360422))
8.016582043889239e+18
As Tadhg McDonald-Jensen indicates, you can also use str.format to get a string representation of your integer in scientific notation:
>>> k = 20685671025767659927959422028 / 2580360422
>>> "{:e}".format(k)
'8.016582e+18'
This may, in fact, be more practical than converting to float. As a general rule of thumb, you should choose a numeric data type based on the precision and range you require, without worrying about what it looks like when printed.
I am getting a large value as a string as follows
s='1234567'
d='12345678912'
I want to do arithmetic as (100/d)*s
To do this, I need to convert the strings to appropriate large values. What would be the way to represent them as a number?
Just convert them using float. Python takes care of creating appropriately large representation. You can read more about Numerals here.
s='1234567'
d='12345678912'
(100/float(d))*float(s)
You could convert them using int, but as #GamesBrainiac pointed, that will work only in Python3; in Python2 it will most of the time give you 0 as result.
(100/int(d))*int(s)
If s and d are large e.g., thousands of digits then you could use fractions module to find the fraction:
from fractions import Fraction
s = int('1234567')
d = int('12345678912')
result = Fraction(100, d) * s
print(result)
# -> 30864175/3086419728
float has finite precision; It won't work for very large/small numbers.
What the heck is going on with the syntax to fix a Decimal to two places?
>>> from decimal import Decimal
>>> num = Decimal('1.0')
>>> num.quantize(Decimal(10) ** -2) # seriously?!
Decimal('1.00')
Is there a better way that doesn't look so esoteric at a glance? 'Quantizing a decimal' sounds like technobabble from an episode of Star Trek!
Use string formatting:
>>> from decimal import Decimal
>>> num = Decimal('1.0')
>>> format(num, '.2f')
'1.00'
The format() function applies string formatting to values. Decimal() objects can be formatted like floating point values.
You can also use this to interpolate the formatted decimal value is a larger string:
>>> 'Value of num: {:.2f}'.format(num)
'Value of num: 1.00'
See the format string syntax documentation.
Unless you know exactly what you are doing, expanding the number of significant digits through quantisation is not the way to go; quantisation is the privy of accountancy packages and normally has the aim to round results to fewer significant digits instead.
Quantize is used to set the number of places that are actually held internally within the value, before it is converted to a string. As Martijn points out this is usually done to reduce the number of digits via rounding, but it works just as well going the other way. By specifying the target as a decimal number rather than a number of places, you can make two values match without knowing specifically how many places are in them.
It looks a little less esoteric if you use a decimal value directly instead of trying to calculate it:
num.quantize(Decimal('0.01'))
You can set up some constants to hide the complexity:
places = [Decimal('0.1') ** n for n in range(16)]
num.quantize(places[2])
I have to convert exponential strings, like 6.5235375356299998e-07,
to a float value, and display the result of my computation like 0.00000065235...
How can I do this in a Python program?
6.5235375356299998e-07 is a perfectly legal float even if there is an e in it. You can do the whole calculation with it:
>>> 6.5235375356299998e-07 * 10000000
6.5235375356300001
>>> 6.5235375356299998e-07 + 10000000
10000000.000000652
In the second case, many digits will disappear because of the precision of a python's float.
If you need the string representation without e, try this:
>>> '{0:.20f}'.format(6.5235375356299998e-07)
'0.00000065235375356300'
but it will become a string and you won't be able to do any calculus with it any more.