将Numpy数组的浮点数按比例转换为整型(平衡化学方程)



我有一个平衡化学方程式的代码。唯一的问题是,我想转换的最终解决方案,即1D np数组的浮点数为整数。显然,我不能把它四舍五入到最接近的整数,那样会弄乱平衡。一种方法是将其与将浮点数转换为整数的数字相乘(类型无关)。请看下面的例子。

>>> coeffs=equation_balancer(reactants=["H2","O2"], products=["H2O"])
>>> coeffs
{"H2": 1.0, "O2": 0.5, 'H2O1': 1.0}
>>> import numpy as np
>>>  np.asarray([i for i in coeffs.values()])
array([1. , 0.5, 1.])

如果最后的数组乘以2,那么分数(浮点数)可以被移除。

PS显示上面的例子,我改回np,因为equation_balancer使用scipy. linear .solve来平衡方程。

>>> np.asrray([i for i in coeffs.values()])*2
array([2., 1., 2.])

如何得到这个数字与数组相乘给整数值数组?数组的实际类型不重要。

一种方法是将数组乘以最大分母,即10的倍数。然后找出最大公因数:

>>> c=np.asrray([i for i in coeffs.values()])*10
>>> factor = np.gcd.reduce(c.astype(int))
>>> factor
5
>>> c/factor
array([2., 1., 2.])

在上面的例子中,找到由小数点后位数定义的10*n是至关重要的。我现在不知道怎么写代码。还有其他更合适的方法吗?任何帮助。

这似乎可以工作:

(关于如何将浮点数转换为"最小值"元组的SO答案)整数分子和整数分母——而不是一些大得出奇的分子和分母)

import numpy as np
from fractions import Fraction
# A configurable param.
# Keep this small to avoid frekish large results.
# Increase it only in rare cases where the coeffs
# span a "huge" scale.
MAX_DENOM = 100
fractions = [Fraction(val).limit_denominator(MAX_DENOM)
for val in coeffs.values()]
ratios = np.array([(f.numerator, f.denominator) for f in fractions])
# As an alternative to the above two statements, uncomment and use
# below statement for Python 3.8+
# ratios = np.array([Fraction(val).limit_denominator(MAX_DENOM).as_integer_ratio()
#                    for val in coeffs.values()])
factor = np.lcm.reduce(ratios[:,1])
result = [round(v * factor) for v in coeffs.values()]
# print
result

coeffs = {"H2": 1.0, "O2": 0.5, 'H2O1': 1.0}的输出:

[2, 1, 2]

coeffs = {"H2": 0.5, "N2":0.5, "O2": 1.5, "H1N1O3":1.0}输出:

[1, 1, 3, 2]

coeffs = {"H2": 1.0, "O3": (1/3), "H2O1":1.0}输出:

[3, 1, 3]

coeffs = {"H4": 0.5, "O7": (1/7), "H2O1":1.0}的输出:

[7, 2, 14]

coeffs = {"H2": .1, "O2": 0.05, 'H2O1': .1}的输出:

[2, 1, 2]

我对我的解决方案并不完全满意但它似乎工作得很好,让我知道你的想法,我实际上是将float转换为字符串并计算小数点后的字符数,只要值始终是float

它就会工作
import numpy as np
coeffs = {"H2": .1, "O2": 0.05, 'H2O1': .1}
n = max([len(str(i).split('.')[1]) for i in coeffs.values()])
c=np.array([i for i in coeffs.values()])*10**n
factor = np.gcd.reduce(c.astype(np.uint64))
print((c/factor).astype(np.uint64))

来源等解决方案:查找小数点的简便方法

测试:运行一些可能的困难情况,例如转换回

primes = [3,5,7,11,13,17,19,23,29,79] ## some prime numbers 
primes_over_1 = [1/i for i in primes]
for i in range(1, len(primes_over_1) - 1):
coeffs = {"H2": primes_over_1[i-1], "O2": primes_over_1[i], 'H2O1': primes_over_1[i+1]}
print('coefs: ', [a for a in coeffs.values()])
n = max([len(str(a).split('.')[1]) for a in coeffs.values()])
c=np.array([a for a in coeffs.values()])*10**n
factor = np.gcd.reduce(c.astype(np.uint64))
coeffs_asInt = (c/factor).astype(np.uint64)
print('as int:', coeffs_asInt)
coeffs_back = coeffs_asInt.astype(np.float64)*(factor/10**n)
coeffs_back_str = ["{0:.16g}".format(a) for a in coeffs_back] 
print('back:  ', coeffs_back_str)
print('########################################################n')

输出:

coefs:  [0.3333333333333333, 0.2, 0.14285714285714285]
as int: [8333333333333333 5000000000000000 3571428571428571]
back:   ['0.3333333333333334', '0.2', '0.1428571428571428']
########################################################
coefs:  [0.2, 0.14285714285714285, 0.09090909090909091]
as int: [5000000000000000 3571428571428571 2272727272727273]
back:   ['0.2', '0.1428571428571428', '0.09090909090909093']
########################################################
coefs:  [0.14285714285714285, 0.09090909090909091, 0.07692307692307693]
as int: [14285714285714284  9090909090909092  7692307692307693]
back:   ['0.1428571428571428', '0.09090909090909093', '0.07692307692307694']
########################################################
coefs:  [0.09090909090909091, 0.07692307692307693, 0.058823529411764705]
as int: [2840909090909091 2403846153846154 1838235294117647]
back:   ['0.09090909090909091', '0.07692307692307693', '0.05882352941176471']
########################################################
coefs:  [0.07692307692307693, 0.058823529411764705, 0.05263157894736842]
as int: [2403846153846154 1838235294117647 1644736842105263]
back:   ['0.07692307692307693', '0.05882352941176471', '0.05263157894736842']
########################################################
coefs:  [0.058823529411764705, 0.05263157894736842, 0.043478260869565216]
as int: [1838235294117647 1644736842105263 1358695652173913]
back:   ['0.05882352941176471', '0.05263157894736842', '0.04347826086956522']
########################################################
coefs:  [0.05263157894736842, 0.043478260869565216, 0.034482758620689655]
as int: [6578947368421052 5434782608695652 4310344827586207]
back:   ['0.05263157894736842', '0.04347826086956522', '0.03448275862068966']
########################################################
coefs:  [0.043478260869565216, 0.034482758620689655, 0.012658227848101266]
as int: [21739130434782608 17241379310344828  6329113924050633]
back:   ['0.04347826086956522', '0.03448275862068966', '0.01265822784810127']
########################################################

最新更新