Спасибо за ваши ответы.Большинство из них были очень хорошими и содержали хорошие ссылки, поэтому я просто скажу это и отвечу на свой вопрос.
Каспин разместил эту ссылку .
Он также упомянул, что Google Testsиспользовал сравнение ULP, и когда я посмотрел на код Google, я увидел, что они упомянули ту же самую точную ссылку на cygnus-software.
В итоге я реализовал некоторые алгоритмы на C как расширение Python, а затем обнаружил, чтоЯ мог бы сделать это и на чистом Python.Код приведен ниже.
В конце концов, я, вероятно, просто добавлю различия ULP к моей сумке трюков.
Было интересно посмотреть, сколько точек с плавающей запятой находится между тем, что должнобыть двумя равными числами, которые никогда не покидали память.В одной из статей или в коде Google, который я прочитал, говорилось, что 4 было хорошим числом ... но здесь я смог набрать 10.
>>> f1 = 25.4
>>> f2 = f1
>>>
>>> for i in xrange(1, 11):
... f2 /= 10.0 # to cm
... f2 *= (1.0 / 2.54) # to in
... f2 *= 25.4 # back to mm
... print 'after %2d loops there are %2d doubles between them' % (i, dulpdiff(f1, f2))
...
after 1 loops there are 1 doubles between them
after 2 loops there are 2 doubles between them
after 3 loops there are 3 doubles between them
after 4 loops there are 4 doubles between them
after 5 loops there are 6 doubles between them
after 6 loops there are 7 doubles between them
after 7 loops there are 8 doubles between them
after 8 loops there are 10 doubles between them
after 9 loops there are 10 doubles between them
after 10 loops there are 10 doubles between them
Также интересно, сколько существует плавающих точекмежду равными числами, когда один из них записан в виде строки и прочитан обратно.
>>> # 0 degrees Fahrenheit is -32 / 1.8 degrees Celsius
... f = -32 / 1.8
>>> s = str(f)
>>> s
'-17.7777777778'
>>> # floats between them...
... fulpdiff(f, float(s))
0
>>> # doubles between them...
... dulpdiff(f, float(s))
6255L
import struct
from functools import partial
# (c) 2010 Eric L. Frederich
#
# Python implementation of algorithms detailed here...
# from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
def c_mem_cast(x, f=None, t=None):
'''
do a c-style memory cast
In Python...
x = 12.34
y = c_mem_cast(x, 'd', 'l')
... should be equivilent to the following in c...
double x = 12.34;
long y = *(long*)&x;
'''
return struct.unpack(t, struct.pack(f, x))[0]
dbl_to_lng = partial(c_mem_cast, f='d', t='l')
lng_to_dbl = partial(c_mem_cast, f='l', t='d')
flt_to_int = partial(c_mem_cast, f='f', t='i')
int_to_flt = partial(c_mem_cast, f='i', t='f')
def ulp_diff_maker(converter, negative_zero):
'''
Getting the ulp difference of floats and doubles is similar.
Only difference if the offset and converter.
'''
def the_diff(a, b):
# Make a integer lexicographically ordered as a twos-complement int
ai = converter(a)
if ai < 0:
ai = negative_zero - ai
# Make b integer lexicographically ordered as a twos-complement int
bi = converter(b)
if bi < 0:
bi = negative_zero - bi
return abs(ai - bi)
return the_diff
# double ULP difference
dulpdiff = ulp_diff_maker(dbl_to_lng, 0x8000000000000000)
# float ULP difference
fulpdiff = ulp_diff_maker(flt_to_int, 0x80000000 )
# default to double ULP difference
ulpdiff = dulpdiff
ulpdiff.__doc__ = '''
Get the number of doubles between two doubles.
'''