Posts: 4,647
Threads: 1,494
Joined: Sep 2016
i have a giant number in a str. i want to double it and get a str result, keeping all of the precision. int(number)*2 can't do this because the number may not be whole. float(number)*2 can't do this because the precision needed may exceed what float supports. what can do this?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 4,790
Threads: 76
Joined: Jan 2018
Jul-15-2023, 07:08 PM
(This post was last modified: Jul-15-2023, 07:08 PM by Gribouillis.)
For integers, Python int type suffices
>>> number = "23278327809283209832832093822093820938029830398320938209"
>>> str(2 * int(number))
'46556655618566419665664187644187641876059660796641876418' Using gmpy2's mpz type
>>> number = "23278327809283209832832093822093820938029830398320938209"
>>> from gmpy2 import mpz
>>> double = 2 * mpz(number)
>>> double
mpz(46556655618566419665664187644187641876059660796641876418)
>>> str(double)
'46556655618566419665664187644187641876059660796641876418'
>>> Also for real numbers
>>> number = "23278327809283209832832093822093820938029830398320938209.23232332323232323"
>>> import gmpy2
>>> gmpy2.get_context().precision = 500
>>> from gmpy2 import mpfr
>>> double = 2 * mpfr(number)
>>> str(double)
'46556655618566419665664187644187641876059660796641876418.464646646464646460000000000000000000000000000000000000000000000000000000000000000000000000000001'
Posts: 1,950
Threads: 8
Joined: Jun 2018
Maybe some simple doubling function?
def double(text):
doubled = []
carry = 0
for num in text[::-1]:
if num in ('.', ','):
doubled.append(num)
else:
quotient, reminder = divmod(2 * int(num), 10)
doubled.append(str(reminder+carry))
carry = quotient
if carry:
doubled.append(str(carry))
return ''.join(doubled[::-1])
for num in ("1", "10", "12.5", "1.9", "99", "99.7899", "99.999"):
print(f"{num}, {double(num)}")
1, 2
10, 20
12.5, 25.0
1.9, 3.8
99, 198
99.7899, 199.5798
99.999, 199.998
Gribouillis likes this post
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 4,790
Threads: 76
Joined: Jan 2018
Jul-16-2023, 03:56 PM
(This post was last modified: Jul-16-2023, 03:57 PM by Gribouillis.)
A faster version using Python's arbitrarily sized integers
def double(text):
parts = text.split('.', 1)
a, b = parts if len(parts) == 2 else (parts[0], '')
shift = len(b)
n = str(int(a + b) * 2)
if shift:
return f'{n[:-shift]}.{n[-shift:]}'
else:
return n
for num in ("1", "10", "12.5", "1.9", "99", "99.7899", "99.999"):
print(f"{num}, {double(num)}") This code assumes that the initial string doesn't have an exponential part such as 31.4e-1
Posts: 4,647
Threads: 1,494
Joined: Sep 2016
so there is nothing to do this already defined in some module; i must pass along this or some definition to do it? i don't think there will be exponentials but i am not 100% sure. my earliest worry when thinking about doing my own function was complex numbers. these will be typically more than 100 digits, possibly over 2000, but always in decimal. so, this function will have to check types or try/except everything.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 582
Threads: 1
Joined: Aug 2019
Jul-17-2023, 08:39 AM
(This post was last modified: Jul-17-2023, 08:59 AM by ibreeden.)
(Jul-16-2023, 11:25 PM)Skaperen Wrote: so there is nothing to do this already defined in some module But there is, I thought you knew. It is decimal for computations with arbitrary precision.
import decimal
number = "23278327809283209832832093822093820938029830398320938209.23232332323232323"
decimal.getcontext().prec = len(number) # Set the precision. (Perhaps decimal point should not be counted.)
print(number)
print(decimal.Decimal(number) * decimal.Decimal(2)) Output: 23278327809283209832832093822093820938029830398320938209.23232332323232323
46556655618566419665664187644187641876059660796641876418.46464664646464646
Gribouillis and Skaperen like this post
Posts: 4,647
Threads: 1,494
Joined: Sep 2016
is there any limit to precision setting for decimal? will a few million digits work on a 4 GB system? how can the precision be restored to what it originally was (in a function to do the doubling)?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 582
Threads: 1
Joined: Aug 2019
Jul-19-2023, 06:41 AM
(This post was last modified: Jul-19-2023, 07:25 AM by ibreeden.)
There is indeed a limit to the number of digits, defined by decimal.MAX_PREC , which is 999.999.999.999.999.999 on 64-bit platforms. So on a system with 4 GB RAM the number of digits will be limited by the available RAM. But this will be the same with every other method you choose. This is not entirely true because we do not know how many times the data is copied internally (from string to decimal input -> to decimal output and back to string may need 4 times the number of bytes of the input string). But I guess the number of digits will not be more than some Millions and you have 4 Billions bytes of memory so I expect no problems.
About the other question, I found this example:
from decimal import localcontext
with localcontext() as ctx:
ctx.prec = 42 # Perform a high precision calculation
s = calculate_something()
s = +s # Round the final result back to the default precision It is explained in the manual.
Posts: 4,647
Threads: 1,494
Joined: Sep 2016
it looks like those limits will not obstruct my needs.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
|