python - 如何在 Python 中得到 10**20 + 10**-20 的精确结果?它给了我 1e+20

标签 python math equation exponent largenumber

我正在编写一个代码来求解二年级方程,它运行良好。 但是,当我输入以下等式时:

x^2 + (10^(20) + 10^(-20)) + 1 = 0

(是的,我的输入是 10**20 + 10**(-20)
我得到:

x1 = 0
x2 = -1e+20

但是,它将 (10^(20) + 10^(-20) 视为 10e+20,而如果您进行数学计算:

这是 LaTeX 格式的公式:

LaTeX formatted formula

几乎 10^20 但不是 10^20。
我怎样才能获得该操作的准确结果,以便我可以获得 x2 中方程的准确值?

我的代码如下:

#===============================Función para obtener los coeficientes===============================

#Se van a anidar dos funciones. Primero la de coeficientes, luego la de la solución de la ecuación.
#Se define una función recursiva para obtener los coeficientes de la ecuación del usuario
def cof():
  #Se determina si el coeficiente a introducir es un número o una cadena de operaciones
  op = input("Si tu coeficiente es un número introduce 1, si es una cadena de operaciones introduce 2")
  #Se compara la entrada del usuario con la opción.
  if op == str(1):
    #Se le solicita el número
    num = input("¿Cuál es tu número?")
    #Se comprueba que efectívamente sea un número
    try:
      #Si la entrada se puede convertir a flotante
      float(num)
      #Se establece el coeficiente como el valor flotante de la entrada
      coef = float(num)
      #Se retorna el valor del coeficiente
      return coef
    #Si no se pudo convertir a flotante...
    except ValueError:
      #Se le informa al usuario del error
      print("No introdujiste un número. Inténtalo de nuevo")
      #Se llama a la función de nuevo
      return cofa()
  #Si el coeficiente es una cadena (como en 10**20 + 10**-20)
  elif op == str(2):
    #La entrada se establece como la entrada del usuario
    entrada = input("Input")
    #Se intenta...
    try:
      #Evaluar la entrada. Si se puede...
      eval(entrada)
      #El coeficiente se establece como la evaluación de la entrada
      coef = eval(entrada)
      #Se regresa el coeficiente
      return coef
    #Si no se pudo establecer como tal...
    except:
      #Se le informa al usuario
      print("No introdujiste una cadena de operaciones válida. Inténtalo de nuevo")
      #Se llama a la función de nuevo
      return cofa()
  #Si no se introdujo ni 1 ni 2 se le informa al usuario
  else:
    #Se imprime el mensaje
    print("No introdujiste n ni c, inténtalo de nuevo")
    #Se llama a la función de nuevo
    return cof()

#===============================Función para resolver la ecuación===============================
#Resuelve la ecuación
def sol_cuadratica():

  #Se pide el valor de a
  print("Introduce el coeficiente para a")
  #Se llama a cof y se guarda el valor para a
  a = cof()
  #Se pide b
  print("Introduce el coeficiente para b")
  #Se llama cof y se guarda b
  b = cof()
  #Se pide c
  print("Introduce el coeficiente para c")
  #Se llama cof y se guarda c
  c = cof()
  #Se le informa al usuario de la ecuación a resolver
  print("Vamos a encontrar las raices de la ecuación {}x² + {}x + {} = 0".format(a, b, c))
  #Se analiza el discriminante
  discriminante = (b**2 - 4*a*c)
  #Si el discriminante es menor que cero, las raices son complejas
  if discriminante < 0:
    #Se le informa al usuario
    print("Las raices son imaginarias. Prueba con otros coeficientes.")
    #Se llama a la función de nuevo
    return sol_cuadratica()
  #Si el discriminante es 0, o mayor que cero, se procede a resolver
  else:   
    #Ecuación para x1
    x1 = (-b + discriminante**(1/2))/(2*a)
    #Ecuación para x2
    x2 = (-b - discriminante**(1/2))/(2*a)
    #Se imprimen los resultados
    print("X1 = " + str(x1))
    print("X2 = " + str(x2))

sol_cuadratica()

忽略评论,我来自西类牙语国家。

最佳答案

机器浮点类型的局限性是将一个非常小的数加到一个非常大的数上时,小数被忽略的原因。

这种现象称为吸收或抵消。

使用自定义浮点对象(如 decimal 模块)你可以达到任何精度(计算速度较慢,因为浮点现在被模拟,而不依赖于机器 FPU 功能不再)

来自decimal module docs :

Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem

这可以通过更改以下全局参数 decimal.getcontext().prec

来实现
import decimal
decimal.getcontext().prec = 41  # min value for the required range

d = decimal.Decimal(10**20)
d2 = decimal.Decimal(10**-20)

现在

>>> d+d2
Decimal('100000000000000000000.00000000000000000001')

正如评论中所建议的那样,对于较小的数字,让 decimal 模块通过对已经存在的 Decimal 对象使用幂运算符来处理除法会更安全(即使在这里,结果是一样的):

d2 = decimal.Decimal(10)**-20

因此您可以使用 decimal.Decimal 对象代替原生 float 进行计算。

关于python - 如何在 Python 中得到 10**20 + 10**-20 的精确结果?它给了我 1e+20,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58189518/

相关文章:

Python 3 PhotoImage 在渲染多次时跨标签重复

python - 神经网络反向传播不训练

python - 在 Python 中使用自定义函数解析方程式

javascript - 如何阻止 javascript 格式化数字?

excel - 如何仅使用函数/方程对表进行排序

ruby - 我怎样才能得到我正在计算的方程来向用户显示 a 值 * x 的二次方。当我尝试对 x 求平方时出现错误

python - 使用字典在列表中查找加起来等于和的一对元素

python - 没有 HTML 转义的 Django 表单值

java - 给定乘数的下一个数字倍数

java - 如何测试 java.lang.Math 方法是否已被调用?