Here is how you can simply turn a float
into an int
, change it, and then turn it back into a float
:
float myFloat = 10.3f;
// Get the bytes making up the float
byte[] bytes = BitConverter.GetBytes(myFloat);
// Make an int out of them
int myInt = BitConverter.ToInt32(bytes, 0);
// Change it
myInt--;
// Get the bytes making up the int
bytes = BitConverter.GetBytes(myInt);
// Make a float out of them
myFloat = BitConverter.ToSingle(bytes, 0);
// gives 10.2999992 or so
BitConverter
even has this built in for the 64-bit equivalent:
double myDouble = 10.3;
long myLong = BitConverter.DoubleToInt64Bits(myDouble);
myLong--;
myDouble = BitConverter.Int64BitsToDouble(myLong); // gives 10.2999999...
However, as Peter Ruderman points out, a simple decrement of the underlying int
doesn't reliably give you the next-smallest float
.
In particular, for negative numbers, you need to increment the integer in order to make the float more negative. For float
zero, the next smallest int
actually corresponds to NaN
, so you need a special case there.
Here are a couple of functions I've knocked together that should cope with these cases in general; it also looks like it sensibly travels between large numbers and positive/negative infinity, too! I've used unsafe conversions to reduce code length, but you can stick to the byte conversions above if you wish:
static unsafe float Increment(float f)
{
int val = *(int*)&f;
if (f > 0)
val++;
else if (f < 0)
val--;
else if (f == 0)
return float.Epsilon;
return *(float*)&val;
}
static unsafe float Decrement(float f)
{
int val = *(int*)&f;
if (f > 0)
val--;
else if (f < 0)
val++;
else if (f == 0)
return -float.Epsilon; // thanks to Sebastian Negraszus
return *(float*)&val;
}
As Jeppe points out, you probably also want to
- Start each function with
if (float.IsNaN(f)) return f;
, so you don't accidentally increment or decrement a NaN
and give something which is a number.
- Also consider checking the input against
float.PositiveInfinity
or .NegativeInfinity
, since, mathematically speaking, those should probably stay constant under increment/decrement.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…