An easy way to check if a BigDecimal number is an integer (whole number)? #89
Replies: 1 comment 1 reply
Check if BigDecimal is an integerWell, there is several ways this can be accomplished. Below are some different ways one can go about it, using the different methods and properties provided by the BigDecimal class. Given an instance of BigDecimal named 'test': Any of the following comparison statements will return true if test is an integer:
Faster?
Define faster. Faster to write or faster to execute? If you are asking about performance, my advice would be to not worry about it and choose whichever expression you think best communicates intent. My guess would be that none of the above expressions are likely to take longer than 1 millisecond to run, even for debug builds, which I would argue is too fast to care about. That said, since I have some idea of what I'm doing, or at least think I do and nobody has called me out yet, I went ahead and wrote some code to time each of the 'is an integer' statements given above, taking care to avoid all of the pitfalls mentioned in the previous paragraph.
So I was correct in that each statement executed in less than a millisecond, but I wasn't expecting them to run quite this fast. Note that the machine I ran them has a 13th Gen Intel Core i7-13620H, which has 10 cores, a base speed of 2.40 GHz for 6 of those cores, and has 64 GB of ram installed. If your hardware is more modest than this, you may wish to repeat these tests yourself as you'll likely see a different result, so I have included the code that I used to produce the above results, in the collapsible section immediately below. Benchmark codeBenchmark codeprivate static void Main(string[] args)
{
BigDecimal test = new BigDecimal(42);
bool b;
long time4;
long time1;
long time0;
long time3;
long time2;
long time5;
Stopwatch sw = Stopwatch.StartNew();
sw.Restart();
b = (test.DecimalPlaces == 0);
time0 = sw.ElapsedTicks;
sw.Restart();
b = BigDecimal.Abs(test).GetDecimalIndex() == ExtendedNumerics.Helpers.BigIntegerHelper.GetLength(test.Mantissa);
time1 = sw.ElapsedTicks;
sw.Restart();
b = test == BigDecimal.Truncate(test);
time2 = sw.ElapsedTicks;
sw.Restart();
b = test.GetFractionalPart() == 0;
time3 = sw.ElapsedTicks;
sw.Restart();
b = test == test.GetWholePart();
time4 = sw.ElapsedTicks;
sw.Restart();
b = test % 1 == 0;
time5 = sw.ElapsedTicks;
Console.WriteLine($"");
Console.WriteLine($"test.DecimalPlaces == 0: {TicksToString(time0)}");
Console.WriteLine($"");
Console.WriteLine($"BigDecimal.Abs(test).GetDecimalIndex() == ExtendedNumerics.Helpers.BigIntegerHelper.GetLength(test.Mantissa): {TicksToString(time1)}");
Console.WriteLine($"");
Console.WriteLine($"test == BigDecimal.Truncate(test): {TicksToString(time2)}");
Console.WriteLine($"");
Console.WriteLine($"test.GetFractionalPart() == 0: {TicksToString(time3)}");
Console.WriteLine($"");
Console.WriteLine($"test == test.GetWholePart(): {TicksToString(time4)}");
Console.WriteLine($"");
Console.WriteLine($"test % 1 == 0: {TicksToString(time5)}");
Console.WriteLine($"");
}
public static string TicksToString(long ticks)
{
if(ticks < TimeSpan.TicksPerMicrosecond)
{
return $"{(ticks * TimeSpan.NanosecondsPerTick)} nanosecond(s) ({ticks} ticks)";
}
else if (ticks < TimeSpan.TicksPerMillisecond)
{
return $"{((double)ticks / (double)TimeSpan.TicksPerMicrosecond)} microsecond(s) ({ticks} ticks)";
}
else
{
return $"{((double)ticks/(double)TimeSpan.TicksPerMillisecond)} millisecond(s) ({ticks} ticks)";
}
} |
Uh oh!
There was an error while loading. Please reload this page.
Hello,
Thank you for the wonderful library; it is used in my variant of NCalc quite successfully. And there, I need to check in many places whether a BigDecimal number has a non-zero fractional part. Is there a faster way to do this than use GetFractionalPart() and check if it is zero?
All reactions