Próbuję wykreślić zestaw ekstremalnych wartości punktowych, które wymagają wysokiej precyzji. Wydaje mi się, że istnieją precyzyjne limity w MATPOTLIB. Nie może iść dalej niż skala 1E28.

To mój kod wyświetlania wykresu.

import matplotlib.pyplot as plt
import numpy as np

x = np.array([1737100, 38380894.5188064386003616016502, 378029000.0], dtype=np.longdouble)
y = np.array([-76188946654889063420743355676.5, -76188946654889063419450832178.0, -76188946654889063450098993033.0], dtype=np.longdouble)

plt.scatter(x, y)
#coefficients = np.polyfit(x, y, 2)
#poly = np.poly1d(coefficients)
#new_x = np.linspace(x[0], x[-1])
#new_y = poly(new_x)
#plt.plot(new_x, new_y)
plt.xlim([x[0], x[-1]])
plt.title('U vs. r')
plt.xlabel('Distance r')
plt.ylabel('Total gravitational potential energy U(r)')
plt.show()

This is my output

Spodziewam się środkowego punktu, który zostanie położony wyższy niż pozostałe dwa punkty. Wymaga bardzo wysokiej precyzji. Jak mogę go skonfigurować?

1
Jimmy Yang 22 październik 2020, 21:22

1 odpowiedź

Najlepsza odpowiedź

Twój obecny problem prawdopodobnie nie ma matplotlib, ale z np.longdouble. Aby odkryć, czy tak jest, uruchom {X1}}. Będzie to zależne od maszyny, ale na mojej maszynie mówi, że używam float128 z poniższym opisem

Machine parameters for float128
---------------------------------------------------------------
precision =  18   resolution = 1.0000000000000000715e-18
machep =    -63   eps =        1.084202172485504434e-19
negep =     -64   epsneg =     5.42101086242752217e-20
minexp = -16382   tiny =       3.3621031431120935063e-4932
maxexp =  16384   max =        1.189731495357231765e+4932
nexp =       15   min =        -max
---------------------------------------------------------------

Precyzja jest tylko oszacowaniem (z powodu reprezentacji dziesiętnej binarnej vs), ale 18 cyfr jest limit float128, a określone numery tylko zaczynają stać się interesujące po tym.

Łatwy test jest drukowany y[1]-y[0] i sprawdź, czy otrzymasz coś innego niż 0.0.

Łatwym rozwiązaniem jest użycie Pythona {X0}} s Ponieważ uchwycić większość różnicy (lub {x1}} 10*y) Ponieważ python ma nieskończoną precyzję int s. Więc coś takiego:

x = np.array([1737100, 38380894.5188064386003616016502, 378029000.0], dtype=np.longdouble)
y = [-76188946654889063420743355676, -76188946654889063419450832178, -76188946654889063450098993033]

plt.scatter(x, [z-y[0] for z in y]) 

enter image description here

Innym rozwiązaniem jest reprezentowanie numerów od samego początku, dzięki czemu wymagają bardziej dostępnej precyzji (tj. Większość usuniętych przesunięć). I inny jest użycie wysokiej precyzyjnej biblioteki pływakowej. To zależy od tego, w jaki sposób chcesz iść.

Warto również zauważyć, że przynajmniej dla mojego systemu, który myślę, jest typowy, domyślny np.float jest float64. Dla float64 Floating Point Mantisaa to 52 bitów, podczas gdy dla float128 Jest to tylko 63 bitów. Lub w dziesiętnie, od około 15 cyfr do 18. Czy nie ma wielkiego precyzyjnego wzrostu do przechodzenia od np.float do np.float128. (Oto dyskusja dlaczego np.longdouble (lub {x7}}) brzmi, jakby dodać wiele precyzji, ale nie.)

(Wreszcie, ponieważ może to spowodować zamieszanie dla niektórych, jeśli tak było np.longdouble lub {X1}} lub np.float128 były przydatne do tego problemu, warto zauważyć, że linia w pytaniu, która ustawia wstępną tablicę " t podaj zamierzoną precyzję np.longdouble. To jest, y=np.array( [-76188946654889063420743355676.5], dtype=np.longdouble) najpierw tworzy i macierz Pythona pływaków, a następnie tworzy z tego macierz, ale precyzja zostanie utracona w tablicy Python. Więc jeśli longdouble były rozwiązaniem, konieczne byłoby inne podejście do inicjowania tablicy.)

1
tom10 23 październik 2020, 16:08