, . IEEE 754. , . ( , ). ( , ).
typedef double Float;
typedef std::uint64_t UInt;
static constexpr UInt HighBit
= std::numeric_limits<UInt>::max() ^ std::numeric_limits<UInt>::max() >> 1;
static UInt EncodingBits(Float x)
{
UInt result;
std::memcpy(&result, &x, sizeof result);
return result;
}
static UInt EncodingMath(Float x)
{
static constexpr int SignificandBits = std::numeric_limits<Float>::digits;
static constexpr int MinimumExponent = std::numeric_limits<Float>::min_exponent;
UInt result = std::signbit(x) ? HighBit : 0;
if (x == 0) return result;
int xe;
Float xf = std::frexp(fabs(x), &xe);
if (xe < MinimumExponent)
{
result |= (UInt) std::ldexp(xf, xe - MinimumExponent + SignificandBits);
}
else
{
result |= (UInt) std::ldexp(xf - .5, SignificandBits);
result |= ((UInt) xe - MinimumExponent + 1) << (SignificandBits-1);
}
return result;
}
static UInt Encoding(Float x)
{
UInt xb = EncodingBits(x);
UInt xm = EncodingMath(x);
if (xb != xm)
{
std::cerr << "Internal error encoding" << x << ".\n";
std::cerr << "\tEncodingBits says " << xb << ".\n";
std::cerr << "\tEncodingMath says " << xm << ".\n";
std::exit(EXIT_FAILURE);
}
return xb;
}
static UInt Distance(Float a, Float b)
{
UInt ae = Encoding(a);
UInt be = Encoding(b);
if (HighBit & ae) ae = HighBit - ae;
if (HighBit & be) be = HighBit - be;
return be - ae;
}
static void Try(Float a, Float b)
{
std::cout << "[" << a << ", " << b << "] contains "
<< Distance(a,b) + 1 << " representable values.\n";
}
int main(void)
{
if (sizeof(Float) != sizeof(UInt))
{
std::cerr << "Error, UInt must be an unsigned integer the same size as Float.\n";
std::exit(EXIT_FAILURE);
}
Float S1 = std::numeric_limits<Float>::denorm_min();
Float N1 = std::numeric_limits<Float>::min();
Float S2 = N1 - S1;
Try( 0, 0);
Try( 0, S1);
Try( 0, S2);
Try( 0, N1);
Try( 0, 1./3);
Try(S1, S1);
Try(S1, S2);
Try(S1, N1);
Try(S1, 1./3);
Try(S2, S2);
Try(S2, N1);
Try(S2, 1./3);
Try(N1, N1);
Try(N1, 1./3);
Try(-0., -0.);
Try(-S1, -0.);
Try(-S2, -0.);
Try(-N1, -0.);
Try(-1./3, -0.);
Try(-S1, -S1);
Try(-S2, -S1);
Try(-N1, -S1);
Try(-1./3, -S1);
Try(-S2, -S2);
Try(-N1, -S2);
Try(-1./3, -S2);
Try(-N1, -N1);
Try(-1./3, -N1);
Try(-0., +0.);
Try(-0., S1);
Try(-0., S2);
Try(-0., N1);
Try(-0., 1./3);
Try(-S1, +0.);
Try(-S1, S1);
Try(-S1, S2);
Try(-S1, N1);
Try(-S1, 1./3);
Try(-S2, +0.);
Try(-S2, S1);
Try(-S2, S2);
Try(-S2, N1);
Try(-S2, 1./3);
Try(-N1, +0.);
Try(-N1, S1);
Try(-N1, S2);
Try(-N1, N1);
Try(-1./3, 1./3);
Try(-1./3, +0.);
Try(-1./3, S1);
Try(-1./3, S2);
Try(-1./3, N1);
Try(-1./3, 1./3);
return 0;
}