Consider the following code and results:
double min = (double) float.MinValue;
double max = (double) float.MaxValue;
double epsilon = (double) float.Epsilon;
double range = max - min;
double delta = range / epsilon;
Console.WriteLine ($@"Min: [{min}].");
Console.WriteLine ($@"Max: [{max}].");
Console.WriteLine ($@"Epsilon: [{epsilon}].");
Console.WriteLine ($@"Range: [{range}].");
Console.WriteLine ($@"Delta: [{delta}].");
// Results:
// Min: [-3.4028234663852886E+38].
// Max: [3.4028234663852886E+38].
// Epsilon: [1.401298464324817E-45].
// Range: [6.805646932770577E+38].
// Delta: [4.8566719410840996E+83].
I was trying out some calculus, trying to get as close to Zero (0)
as possible, and was surprised that I never thought about representing a numeric type's range before.
How would one represent a numeric type's range? In the case above, we're using Double
to represent Single
ranges. For Int32
, we could use Int64
, etc.
Int64
, Double
, and Decimal
, etc.?(float.MaxValue / float.Epsilon)
evaluate to Infinity? Should it not evaluate to a number very close to, but less than float.MaxValue
?The numeric types in any programming language are approximations of mathematical concepts. Since these concepts include infinities, they cannot be represented accurately in real computers.
The range (defined as difference between the maximum and minimum value of a type) can only be represented by a type having a lager range. E.g., you could use decimal
or System.Numerics.BigInteger to represent the range of Int64
. BigInteger
could also be used to represent the range of float
and double
or at least the integer part of it.
float.MaxValue / float.Epsilon
: float.Epsilon
is a positive number smaller than one (public const float Epsilon = 1.401298E-45;
). If you divide a positive number by a positive number smaller than one, the result is lager than this number. E.g., 10 / 0.5 = 20. But since you cannot store a float bigger than float.MaxValue
in a float
, Microsoft decided to assign it Single.PositiveInfinity
instead. They also could have decided the result should have been Single.NaN
(Not a Number), Single.MaxValue
or even to throw an exception. But that's how it was implemented. The Single
type (float
in C#`) complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.