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

Python 按比例将浮点数数组转换为整数(平衡化学方程式),python,arrays,numpy,floating-point,integer,Python,Arrays,Numpy,Floating Point,Integer,我有一个平衡化学方程式的密码。唯一的问题是,我想将最终的解决方案,即1D np浮点数组转换为整数。很明显,我不能直接将它四舍五入到最接近的整数,这会破坏平衡。一种方法是将其与一个数字相乘,该数字将浮点数转换为integerstype不重要。请参见下面的示例 >>> coeffs=equation_balancer(reactants=["H2","O2"], products=["H2O"]) >>>

我有一个平衡化学方程式的密码。唯一的问题是,我想将最终的解决方案,即1D np浮点数组转换为整数。很明显,我不能直接将它四舍五入到最接近的整数,这会破坏平衡。一种方法是将其与一个数字相乘,该数字将浮点数转换为integerstype不重要。请参见下面的示例

>>> 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,因为等式_平衡器使用scipy.linalg.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是至关重要的。我现在不知道怎么编码。还有其他更合适的方法吗?任何帮助。

我对我的解决方案不太满意,但它似乎工作正常,请告诉我您的想法,我基本上是将浮点转换为字符串,并计算小数点后的字符数,只要值始终是浮点,它就可以工作

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')
输出:


我并不完全满意我的解决方案,但它似乎工作正常,让我知道你的想法,我基本上是将浮点转换为字符串,并计算小数点后的字符数,只要值始终是浮点,它就会工作

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')
输出:

这似乎有效:

关于如何将浮点数转换为最小整数分子和整数分母的元组,而不是一些异常大的分子和分母,这要归功于

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
系数的输出={H2:1.0,O2:0.5,'H2O1':1.0}:

系数的输出={H2:0.5,N2:0.5,O2:1.5,H1N1O3:1.0}:

系数的输出={H2:1.0,O3:1/3,H2O1:1.0}:

系数的输出={H4:0.5,O7:1/7,H2O1:1.0}:

系数的输出={H2:.1,O2:0.05,'H2O1':.1}:

这似乎有效:

关于如何将浮点数转换为最小整数分子和整数分母的元组,而不是一些异常大的分子和分母,这要归功于

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
系数的输出={H2:1.0,O2:0.5,'H2O1':1.0}:

系数的输出={H2:0.5,N2:0.5,O2:1.5,H1N1O3:1.0}:

系数的输出={H2:1.0,O3:1/3,H2O1:1.0}:

系数的输出={H4:0.5,O7:1/7,H2O1:1.0}:

系数的输出={H2:.1,O2:0.05,'H2O1':.1}:


你有没有试过解决一个简单的问题,比如coefs={H2:1/3,O2:1/3,'H2O1':1/3}?哪一个应该给出1:1:1这种情况存在吗?编辑:我明白你的意思了,我将你的意思解释为1/3是一个字符串,这意味着没有“.”我用coefs={H2:1/3,O2:1/3,'H2O1':1/3}运行代码,它确实产生[1,1,1],但那个实验并不能证明它适用于所有情况……不,我的意思是,当等式_平衡器为每个组件返回1/3时,将打印为0.3333。我用你的代码得到[-1552204.2910258-1552204.2910258-1552204.2910258],它与np.gcd.reducec.astypenp.int64一起工作,现在我很清楚了。astypeint中的int相当于np.int\ux。这是Windows上的np.int32(即使对于64位),或Linux上的np.int64,请参阅。c大约是3e+15,这当然不适合32位,所以你所有的时间和精力都是+1:你有没有尝试过你的解决方案,比如coefs={H2:1/3,O2:1/3,'H2O1:1/3}?哪一个应该给出1:1:1这种情况存在吗?编辑:我明白你的意思了,我将你的意思解释为1/3是一个字符串,这意味着没有“.”我用coefs={H2:1/3,O2:1/3,'H2O1':1/3}运行代码,它确实产生[1,1,1],但那个实验并不能证明它适用于所有情况……不,我的意思是,当等式_平衡器为每个组件返回1/3时,将打印为0.3333。我用你的代码得到[-1552204.2910258-1552204.2910258-1552204.2910258],它与np.gcd.reducec.astypenp.int64一起工作,现在我很清楚了。astypeint中的int相当于np.int\ux。这是Windows上的np.int32(即使对于64位),或Linux上的np.int64,请参阅。c大约是3e+15,这当然不适合32位,所以你所有的时间和精力都是+1:很好的答案+1,以前从未听说过分数模块,但是你在哪里找到H4或O7,当然不是在这个地球上:很好的答案+1,以前从未听说过分数模块,但是你在哪里找到H4或O7,当然不是在这个地球上:
[3, 1, 3]
[7, 2, 14]
[2, 1, 2]