感谢您的回复。大多数人都很好,并提供了良好的链接,所以我就这样说,回答我自己的问题。
Caspin发布了此链接。
他还提到Google Tests使用ULP比较,当我查看google代码时,我发现它们提到了与cygnus软件相同的确切链接。
我结束了在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 themafter 2 loops there are 2 doubles between themafter 3 loops there are 3 doubles between themafter 4 loops there are 4 doubles between themafter 5 loops there are 6 doubles between themafter 6 loops there are 7 doubles between themafter 7 loops there are 8 doubles between themafter 8 loops there are 10 doubles between themafter 9 loops there are 10 doubles between themafter 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 structfrom functools import partial# (c) 2010 Eric L. Frederich## Python implementation of algorithms detailed here...# from http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htmdef 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 differencedulpdiff = ulp_diff_maker(dbl_to_lng, 0x8000000000000000)# float ULP differencefulpdiff = ulp_diff_maker(flt_to_int, 0x80000000 )# default to double ULP differenceulpdiff = dulpdiffulpdiff.__doc__ = '''Get the number of doubles between two doubles.'''



