4

In Python, is there any way to multiply a float with a very large integer?

As an example, I tried print (10**100000) * 1.414 and it gave me:

OverflowError: long int too large to convert to float

Note that the values (the float and that large number) can be anything. More importantly, I want the exact value (rounded to nearest integer) of expression.

Please provide any solution.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Sushil Verma
  • 659
  • 9
  • 23
  • 4
    "And more importantly, I wanted the exact value of expression" - then why are you using floats? Floating-point operations are almost always inexact, even the operation of converting the source code characters `1.414` into a float. – user2357112 Jun 09 '17 at 16:19

4 Answers4

2

Edit 2:

Ok, I see what you're after:

import mpmath

mpmath.mp.dps = 100005
i = int(mpmath.mpf("1.414") * 10 ** 100000)

print(str(i)[:10])        # 1414000000
print(len(str(i)))        # 100001
print(str(i)[-10:])       # 0000000000
print(str(i).count("0"))  # 99997

And for @Stefan:

int(mpmath.mpf("1.414") * (10 ** 100000 + 1000))

returns

14140000000000000 ... 000000000001414     # string contains 99993 0s
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • 2
    but mpmath is not a python's native module! – Sushil Verma Jun 09 '17 at 16:28
  • 1
    Your result is wrong, since the float is actually 1.4139999999999999236166559057892300188541412353515625 – Stefan Pochmann Jun 09 '17 at 16:29
  • 6
    @Sushil, you never asked for a python native module. – Kevin Rajan Jun 09 '17 at 16:34
  • Does `1.414 * (mpmath.mpf(10.) ** 100000 + 1)` give the same value or a different value? It should give a different value. – Stefan Pochmann Jun 09 '17 at 17:05
  • Yeah, your updated code has enough precision. For **this** case. You hardcoded how much is necessary. Doesn't work in general. Also, you changed one of the values (the float one). The proper setup is like Daniel did it (Setting up two variables `value = 1.414` and `large = 10**100000` and working with those). – Stefan Pochmann Jun 09 '17 at 17:23
  • @Stefan *any* code that starts from `value = 1.414` will fail because native Python floats only have 15 digits of accuracy (it's inherent in the IEEE definition of a floating-point number). – Hugh Bothwell Jun 09 '17 at 17:33
  • @HughBothwell The problem is *"Multiply a **float** and a very large number in python"*. So we're given a **float**, not a string. And yeah, the float's value in the example isn't 1.414. I know that, as I've shown the exact value above. But so what? Starting with `value = 1.414` is failing. It simply is what it is. And it's exactly the given example. Yours isn't. – Stefan Pochmann Jun 09 '17 at 17:42
  • Well, luckily I'm answering Sushil, not you :-) – Hugh Bothwell Jun 09 '17 at 17:45
  • @HughBothwell You **might** be answering what Sushil **meant** to ask, but you're not answering what they actually asked. – Stefan Pochmann Jun 09 '17 at 17:45
2

Convert the float to an integer ratio:

value = 1.414
large = 10**100000

a, b = value.as_integer_ratio()
number, residual = divmod(large * a, b)
number += residual*2 >= b   
Daniel
  • 42,087
  • 4
  • 55
  • 81
  • Not giving more accurate value. I tried your code with 10**100 – Sushil Verma Jun 09 '17 at 16:47
  • @SushilVerma Yeah, that proves you wrong. It gives the **exact** value. – Stefan Pochmann Jun 09 '17 at 16:56
  • @StefanPochmann at 10^100, it is not giving: OverflowError: long int too large to convert to float. That is why, I am claiming that print int((10**100000)*1.414) is giving correct value. I am not sure. – Sushil Verma Jun 09 '17 at 16:58
  • @SushilVerma Yeah, so? – Stefan Pochmann Jun 09 '17 at 16:58
  • 1
    @SushilVerma actually, you are building the product of `1.4139999999999999236166559057892300188541412353515625` with `10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104.0`. So the question is, what is 10**100? – Daniel Jun 09 '17 at 16:59
  • @Daniel Those factors are right, but I don't understand your question what 10**100 is. – Stefan Pochmann Jun 09 '17 at 17:03
  • I am wondering. Why `print int((10**100)*1.414)` and `print (10**(100-3))*1414` are printing different values!! – Sushil Verma Jun 09 '17 at 17:13
  • @SushilVerma That's pretty obvious. You should probably read [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Stefan Pochmann Jun 09 '17 at 17:15
2

If you're looking for the exact value, this means you must have access to 1.414 as a string (otherwise, the value stored in memory isn't exact either).

import decimal

float_string = '1.614' # to show that rounding works
exponent = 100000
decimal.getcontext().prec = exponent + 1

c = 10 ** exponent + 1
d = decimal.Decimal(float_string) * c

print d #1614000.....000002
Jared Goguen
  • 8,772
  • 2
  • 18
  • 36
  • I deleted due to, quoting @Stefan Pochmann, *That's not exact. For example, you get the same value with (Decimal(10 ** 100000) + 1) * Decimal(1.414) but shouldn't.* – Wondercricket Jun 09 '17 at 16:48
  • Also, what you did makes it *worse*, as you're changing the value. And it's not clear how you'd turn the float into a string. – Stefan Pochmann Jun 09 '17 at 16:50
  • @StefanPochmann I'm not sure I understand the first point. Regarding the second point, it seems like OP would have to have access to the value as a string, otherwise 1.414 isn't even stored in memory as an exact value. – Jared Goguen Jun 09 '17 at 17:02
  • @JaredGoguen I know that 1.414 isn't the exact value of the float. That's the point. – Stefan Pochmann Jun 09 '17 at 17:06
0

Since you accept integer approximations, here is a native solution:

def getint(x, y, z):
    z_nu, z_de = z.as_integer_ratio()
    return ((x**y) * z_nu) // z_de

Usage:

>>> getint(2, 3, 5.)
40

>>> getint(10, 100000, 1.414)
1413999999999999923616655905789230018854141235351562500000000...  # truncated
Asclepius
  • 57,944
  • 17
  • 167
  • 143