1

Ich möchte vermeiden, dass mein Code eine fast ganze Zahl für eine ganze Zahl verwechselt. Zum Beispiel hat 58106601358565889 als Quadratwurzel 241,053,109.00000001659385359763188, aber wenn ich den folgenden Booleschen Test verwendet, 58106601358565889 täuschte mich zu denken, dass es ein perfekter Platz war:Große Ganzzahlen von nahen Ganzzahlen in Python unterscheiden

a = 58106601358565889 
b = math.sqrt(a) 
print(b == int(b)) 

Die Genauigkeit ist nicht unbedingt das Problem, denn wenn ich re-check, erhalte ich die richtige (false) Schlussfolgerung:

print(a == b**2) 

Was wäre ein besserer Weg für einen echten Vergleich zu einem in der Nähe integer zu testen? Die math.sqrt ist in einer anderen Definition in meinem Code vergraben, und ich möchte es vermeiden, wenn möglich eine Überprüfung einer Quadratwurzel einzufügen. Ich entschuldige mich, wenn das keine gute Frage ist; Ich bin neu in Python.

+0

Sollte es "wahr" zurückgeben, ist das was du willst? – styvane

+0

Es sollte False zurückgeben, Wenn mein Verständnis korrekt ist – Backtrack

+0

Der erste Druck (b == int (b)) Ich möchte falsch sein. – Jeptha

Antwort

0
import numpy as np 
import math 
from decimal import * 

a = 58106601358565889 
b = np.sqrt(a) 
c = math.sqrt(a) 
d = Decimal(58106601358565889).sqrt() 


print(d) 
print(int(d)) 

print(c) 
print(int(c)) 

print(b) 
print(int(b)) 

o/p

241053109.0000000165938535976 
241053109 
241053109.0 
241053109 
241053109.0 
241053109 

würde ich Gebrauch decimal sagen.

Expected Code:

from decimal import * 
d = Decimal(58106601358565889).sqrt() 
print(d == int(d)) 

o/p

False 
+0

'Decimal' führt Berechnungen immer noch zu einer begrenzten (wenn auch konfigurierbaren) Genauigkeit durch. Wenn Sie alle Ihre Berechnungen in "Dezimal" durchführen, verschieben Sie das Problem auf noch größere Eingabegrößen, es sei denn, Sie führen zusätzliche Konfigurations- und Sekundärprüfungen durch. – user2357112

+0

Danke, Decimal hat es geschafft. Ich hatte von dieser Option nichts gewusst. – Jeptha

+0

Danke user2357112, ich werde in die Grenzen der Präzision für 'Dezimal' schauen müssen. – Jeptha

0

Es ist nicht die Genauigkeit der int, dass das Problem ist - es ist die begrenzte Genauigkeit der Schwimmer

>>> import math 
>>> math.sqrt(58106601358565889) 
241053109.0 
>>> math.sqrt(58106601358565889) - 241053109 
0.0 

ich die doppelte Kontrolle denken würde die offensichtliche Lösung sein

+0

Also ist der Doppel-Check wirklich notwendig? – Jeptha

+0

@Jeptha: Der Doppel-Check ist nicht einmal gut genug; Es hat seine eigenen Probleme. Zum Beispiel schlägt es auf 'a = 100000000000000000001 ** 2' fehl. – user2357112

+0

@Jeptha, alle Schwimmer größer als das wird immer integral sein. Vielleicht können Sie einfach testen '(a == b * b)' –

1

Dies ist nicht eine Frage der Unterscheidung von ganzen Zahlen von nicht-ganzen, weil b wirklich eine ganze Zahl * ist. Die Genauigkeit einer Python-Gleitkommazahl reicht nicht aus, um die Quadratwurzel von auf genügend Stellen darzustellen, um eine ihrer gebrochenen Komponenten zu erhalten. Die zweite Prüfung Sie tat:

print(a == b**2) 

druckt nur False weil während b eine ganze Zahl, b**2 ist noch nicht a.

Wenn Sie testen möchten, ob sehr große Ganzzahlen genaue Quadrate sind, sollten Sie einen Quadratwurzelalgorithmus selbst implementieren.

* wie in 0 Nachkommastellen, nicht wie in isinstance(b, int).

+0

Vielen Dank, dass Sie darauf hingewiesen haben; das war eine schlechte Annahme meinerseits. – Jeptha

0

Sie auch auf der gmpy2 Bibliothek aussehen könnte. Es hat eine Funktion zum Berechnen der ganzen Quadratwurzel und auch der ganzen Quadratwurzel plus Rest. Es gibt keine Präzisionsbeschränkungen.

>>> import gmpy2 
>>> gmpy2.isqrt(58106601358565889) 
mpz(241053109) 
>>> gmpy2.isqrt_rem(58106601358565889) 
(mpz(241053109), mpz(8)) 
>>> 

Disclaimer: Ich gmpy2 halten.