Reputation: 9216
For testing purposes I need to create one positive and one negative denormalized (aka subnormal) float
and double
number in C++.
How can I write/produce such a number?
Upvotes: 4
Views: 2533
Reputation: 1394
The following is a demonstration of how a denormalized IEEE-754 floating point value can be formed in memory.
const uint32_t denormal_as_int[2] = {0x0000001, 0x00000000};
double denormal;
memcpy(&denormal, &denormal_as_int, sizeof(denormal));
The standard way of doing this is of course the one mentioned by @DietmarKüh
Upvotes: 1
Reputation: 2131
For full flexibility and coverage, create a union with an unsigned integer value and a floating-point value of the same size. Probably unsigned int + float for 32-bit values, and unsigned long + double for 64-bit values. Store your desired denorm value in the integer field, and read out the corresponding floating-point value. If you want to get fancy, specify the integer with bit fields, for the sign, exponent and fraction portions of your floating point number.
32-bit denorms are in the range [0x00000001
, 0x007fffff
] for positive values, and [0x80000001
, 0x807fffff
] for negative denorms.
64-bit denorms are in the range [0x0000000000000001
, 0x000fffffffffffff
] for positive values, and [0x8000000000000001
, 0x800fffffffffffff
] for negative denorms.
If you use bit fields in your translation union, then the sign bit is arbitrary, exponent is zero, and the fraction can be any value but zero.
Upvotes: 3
Reputation: 10007
Another approach is, obviously, take the minimal normalized value DBL_MIN
(or, well, std::numeric_limits<double>::min()
) and divide it by something; similarly for float
. Invert the sign for negative subnormal.
Upvotes: 1
Reputation: 154045
You could use -std::numeric_limits<T>::denorm_min()
and std::numeric_limits<T>::denorm_min()
. It is just incidental that the produced denormalized values have a special characteristic. If you don't want that, multiply by some reasonably small integer value.
Upvotes: 4