Reputation: 10204
How could I write a generic C routine num(a,b) that calculates the number of floating-point number in between a and b? Assume both a and b are of type double
.
For example, num(0,1e-17)
should return the number of doubles in between 0
and 1e-17
.
Upvotes: 3
Views: 68
Reputation: 153650
@Pascal Cuoq well explains the lmitations of double
representaiton, endian, etc.
Below is a variation on how to extract a sequence number for the 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;
}
Upvotes: 3
Reputation: 80305
This answer assumes in addition to “both a
and b
are of type double
” that double
maps to IEEE 754 double-precision, and that its representation, accessed as a uint64_t
integer, is interpreted with the same endianness as floating-point numbers. This is the case on mainstream compilation platforms.
Under these hypotheses, the representations of positive and negative floating-point numbers are consecutive 64-bit integers. So in order to compute how many numbers there are between two floating-point numbers of the same sign, compute the number of integers between their representations interpreted as 64-bit unsigned integers:
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 */
If the floating-point numbers do not have the same sign, compute the number of floating-point numbers between the negative one and -0.0
, and the number of floating-point numbers between the positive one and +0.0
, using the above method. Then sum these two parts.
Upvotes: 7