我想制作一个可以对大数字执行数学运算的脚本,同时保持所需的精度。我很久以前尝试过,而且除此之外,分裂是最糟糕的部分,所以我想我这次尝试开始。
基本上,我使用str
输入,因为它们显然保持完全准确,并且我想对它们进行整数计算,以便浮点数不会丢失。我目前通过在计算之前删除小数点,然后尝试重新添加它来做到这一点,但我无法弄清楚如何。
通过乘法,您可以通过在两个数字中添加小数点的剩余数量来计算小数。不幸的是,这种方法似乎与分裂无关。我之前尝试过编码长分区,但如果涉及到浮动,那么它又是一个尴尬的问题。
这是我目前获得的代码,删除了一些非工作部分:
from __future__ import division
def _divide(a, b, precision):
count = 0
while a and count < precision:
for num in str(int(a // b)):
yield int(num)
count += 1
a = a % b * 10
def divide(a, b, precision=100, round_int=True):
result = []
a = str(a)
b = str(b)
#Check for negative numbers
a_neg = a[0] == '-'
b_neg = b[0] == '-'
if a_neg and not b_neg or b_neg and not a_neg:
result.append('-')
#Process number strings
a_split = a.split('.')
b_split = b.split('.')
try:
a = abs(int(a_split[0] + a_split[1]))
except IndexError:
a = abs(int(a_split[0]))
try:
b = abs(int(b_split[0] + b_split[1]))
except IndexError:
b = abs(int(b_split[0]))
#Calculate number
result += list(_divide(a, b, precision=precision+round_int))
if not round_int:
return ''.join(map(str, result))
#Round last integer
last_int = int(result.pop(-1))
index = -1
if last_int >= 5:
try:
result[index] += 1
except TypeError:
index -= 1
result[index] += 1
#Lower any integers above 10
while True:
if result[index] == '.':
index -= 1
if result[index] > 9:
result[index] -= 10
if result[index-1] == '.':
index -= 1
result[index-1] += 1
else:
return ''.join(map(str, result)).rstrip('.')
index -= 1
a = '365.72'
b = '2247.7'
print divide(a, b, 9, False)
print float(a) / float(b)
我刚刚制定了一个快速的hacky方法,它使用内置浮点除法来计算小数的位置,但显然它并不理想,因为它在1e300
之后失败:
cheat_div = str(abs(float(a) / float(b)))
if 'e' in cheat_div:
num_decimals = int(cheat_div.split('e')[1])
if num_decimals > 1:
num_decimals += 1
else:
if cheat_div.startswith('0.'):
num_decimals = 2 + len(cheat_div[2:].lstrip('0')) - len(cheat_div)
else:
try:
num_decimals = cheat_div.index('.')
except ValueError:
num_decimals = 0
while not result[is_negative]:
del result[is_negative]
if num_decimals:
if num_decimals > 0:
result = result[:is_negative+num_decimals] + ['.'] + result[is_negative+num_decimals:]
else:
result = result[:is_negative] + ['0', '.'] + ['0'] * -num_decimals + result[is_negative:]