我怎样才能编写一个通用的C例程num(a,b)来计算a和b之间的浮点数?假设a和b都是double
类型。
例如,num(0,1e-17)
应返回0
和1e-17
之间的双打数。
答案 0 :(得分:7)
此答案假设“a
和b
都属于double
类型”double
映射到IEEE 754双精度,以及它的表示形式,作为uint64_t
整数访问,被解释为具有与浮点数相同的字节序。主流编译平台就是这种情况。
在这些假设下,正浮点数和负浮点数的表示是连续的64位整数。因此,为了计算相同符号的两个浮点数之间存在多少个数,计算它们的表示之间的整数数,将其解释为64位无符号整数:
double a, b;
…
uint64_t a1, b1;
memcpy(&a1, &a, 8);
memcpy(&b1, &b, 8);
int64_t d = a1 - b1;
if (d<0) d = -d;
d++; /* account for both a and b e.g. if a==b, they enclose one FP number */
如果浮点数不具有相同的符号,则计算负数和-0.0
之间的浮点数,以及正数和{{之间的浮点数。 1}},使用上述方法。然后总结这两部分。
答案 1 :(得分:3)
@Pascal Cuoq很好地解释了double
代表,endian等的模仿。
以下是如何提取double
的序列号的变体。
unsigned long long SequenceNumber(double d) {
assert(sizeof(double) == sizeof(uint64_t));
union {
double d;
uint64_t u64;
int64_t i64;
} x = {d};
uint64_t y;
if (x.i64 < 0) {
y = 0xFFFFFFFFFFFFFFFF - x.u64;
} else {
y = 0x8000000000000000 + x.u64;
}
return y;
}
unsigned long long SequenceDiff(double a, double b) {
unsigned long long sna = SequenceNumber(a);
unsigned long long snb = SequenceNumber(b);
return sna > snb ? sna - snb : snb - sna;
}