Dire che ho due float Python a
e b
, c'è un modo semplice per scoprire quanti numeri reali rappresentabili sono tra i due nella rappresentazione IEEE-754 (o qualsiasi rappresentazione utilizzata dalla macchina utilizzata)?Numero di galleggianti tra due galleggianti
risposta
io don'tknow quello che verrà utilizzato per questo - ma, se entrambi i carri hanno lo stesso esponente, dovrebbe essere possibile. Poiché l'esponente viene mantenuto sui bit di ordine elevato, il caricamento dei byte float (8 byte in questo caso) come numero intero e la sottrazione di uno da un altro dovrebbe fornire il numero desiderato. Io uso il modello struct per imballare i carri ad una rappresentazione binaria, e quindi decomprimere quelli come (C, 8 byte) lunghe interi:
>>> import struct
>>> a = struct.pack("dd", 1.000000,1.000001)
>>> b = struct.unpack("ll",a)
>>> b[1] - b[0]
4503599627
>>> a = struct.pack("dd", 1.000000000,1.000000001)
>>> b = struct.unpack("ll",a)
>>> b[1] - b[0]
4503600
>>>
l'esponente non ha importanza, ma il segno lo fa. –
+1; bella risposta. Tuttavia, non funzionerà su sistemi con C a 32 bit. Per sicurezza, usa "
Per completare, si potrebbe anche ricordare che questa soluzione funziona solo con i formati IEEE 754. In pratica, non si tratta di una restrizione, anche se --- è molto difficile trovare Python in esecuzione su una piattaforma che utilizza doppi non IEEE 754. –
Per i numeri positivi b> a> 0, la risposta è circa:
(2**52) ** (log(b,2) - log(a,2))
Ci sono 52 bit della mantissa (oltre il implicita 1), moltiplicata per 2 elevato ad un esponente.
Quindi ci sono 2 ** 52 numeri nella gamma [1: 2) come nel range [1024: 2048)
La teoria è buona, ma non funziona per me quando i numeri float sono troppo vicini. Probabilmente a causa del fatto che il calcolo del log introduce alcuni arrotondamenti. – jsbueno
per quanto ne so, carri IEEE754 hanno una proprietà interessante. Se si dispone di float f, quindi
(*(int*)&f + 1)
in determinate condizioni, è il successivo numero a virgola mobile rappresentabile. Quindi per i galleggianti a e b
*(int*)&a - *(int*)&b
Vi darà la quantità di numeri in virgola mobile tra quei numeri.
Vedere http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm per ulteriori informazioni.
L'unico requisito è che abbiano lo stesso segno, e né Nan né inf. –
Sembra che sia * la * risposta alla domanda, ma manca una parte: come si fa in Python? – Bolo
Sebbene questo non risponda alla domanda per Python, questa è un'ottima risposta. Anche il mio libro di testo su "Metodi computazionali" concorda con questo. Qualcuno sa come convertire questo in Python? – Dragontamer5788
Guarderei la funzione frexp nel modulo matematico. L'esempio seguente estrae la mantissa e la converte in un numero intero. La differenza dovrebbe essere il numero di float tra i due valori.
>>> math.frexp(1.1234567890)[0] * 2**53
5059599576307254.0
>>> math.frexp(1.12345678901)[0] * 2**53
5059599576352290.0
Il seguente codice dovrebbe farlo:
import math
import sys
def delta(x,y):
'''Return the number of floats between x and y.'''
x = float(x)
y = float(y)
if x == y:
return 0
elif x < y:
return -delta(y,x)
else:
x_mant, x_exp = math.frexp(x)
y_mant, y_exp = math.frexp(y)
x_int = int(x_mant * 2**(sys.float_info.mant_dig + x_exp - y_exp))
y_int = int(y_mant * 2**sys.float_info.mant_dig)
return x_int - y_int
print(delta(1.123456789, 1.1234567889999))
450
>>>
Solo per curiosità, che cosa avete bisogno di questa informazione per? –
Come intendete? Due galleggianti specifici o in generale? E vuoi essere in grado di farlo da Python o vuoi fare i calcoli manualmente? – terminus
Voglio confrontare due numeri in virgola mobile per determinare se sono uguali a una precisione vicina ma non uguale alla precisione della rappresentazione. Sono interessato a farlo in Python. Vedi la funzione AlmostEqual2sComplement su http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm - So che posso farlo con cose come (ab)/a
astrofrog