I'm working on an importer for LitJson, to import float values from ints, and doubles, and if overflow-checking is enabled, I want to wrap a potential overflow exception in a JsonException with a bit more information about the failure.
Right now my code looks like this, and I don't know if I need to/can check if the context is checked or not:
private static float DoubleFloatImporter(double value) {
try
{
return (float)value;
}
catch (Exception ex)
{
throw new JsonException("Value is not a valid Single", ex);
}
}
CodePudding user response:
You may be thinking of checked
and unchecked
contexts, but these are not relevant for your example, the explicit conversion (cast) from double
to float
(so from double-precision binary floating point to single-precision).
A finite double
value may round to an infinite float
value (either float.PositiveInfinity
or float.NegativeInfinity
).
For example DoubleFloatImporter(1.23e123)
. As a double, the input 1.23e123
will be represented as a finite value, but when cast to float
, the nearest representable value will be interpreted as ∞.
Edit: As I say in comments, something like:
private static float DoubleFloatImporter(double value) {
var converted = (float)value;
if (!float.IsFinite(converted))
throw new JsonException("Converted value would become infinite or not a number");
return converted;
}
may suit your need.
CodePudding user response:
What about something like this:
static float DoubleFloatImporter(double value)
{
if (double.IsPositiveInfinity(value))
{
return float.PositiveInfinity;
}
if (double.IsNegativeInfinity(value))
{
return float.NegativeInfinity;
}
if (value > Single.MaxValue || value < Single.MinValue)
{
throw new OverflowException($"'{value}' doesn't fit");
}
return (float)value; //Single.CreateChecked(value);
}
Some examples:
using System.Runtime.CompilerServices;
Convert(1.0);
Convert(double.MaxValue);
Convert(double.PositiveInfinity);
Convert(double.NegativeInfinity);
Convert((double)float.MaxValue 100);
Convert((double)float.MaxValue * 2);
Convert(double.NaN);
static void Convert(double v, [CallerArgumentExpression("v")] string arg1Exp = "?")
{
try
{
var f = DoubleFloatImporter(v);
Console.WriteLine($"{arg1Exp} -> {f}");
}
catch (Exception ex)
{
Console.WriteLine($"{arg1Exp} -> {ex.Message}");
}
}
The output:
1.0 -> 1
double.MaxValue -> '1.7976931348623157E 308' doesn't fit
double.PositiveInfinity -> ∞
double.NegativeInfinity -> -∞
(double)float.MaxValue 100 -> 3.4028235E 38
(double)float.MaxValue * 2 -> '6.805646932770577E 38' doesn't fit
double.NaN -> NaN