Test whether a decimal value can be converted to double - c#

What's a good method to test whether a decimal value can be converted to double without throwing an exception and preferrably without converting to and parsing from a string?
I can test for compatibility with the long or int types like this: (yet untested)
if (value == decimal.Truncate(value))
{
if (value >= int.MinValue && value <= int.MaxValue)
return (int)value;
if (value >= long.MinValue && value <= long.MaxValue)
return (long)value;
return value.ToStringInvariant();
}
// Now try double, else revert to string again
This method should be used to serialise a decimal value to something that can be sent to JavaScript. Here, MessagePack is used but JSON should have the same constraints. decimal is not supported in both.
I could just always send the value as string but I'd like to save a bit bandwidth and use the simplest type that can represent the value (with decent precision).
PS: This doesn't compile:
if (value >= double.MinValue && value <= double.MaxValue)
return (double)value;
I cannot compare decimal with double. What would be a good solution, if this is a good path at all?

What's a good method to test whether a decimal value can be converted to double without throwing an exception?
static bool CanBeConvertedToDouble(decimal d)
{
return true;
}
:)
All decimals can be converted to double.
Note that doing so will possibly lose immense amounts of precision. A decimal has about 29 decimal places of precision; a double has only 15 or so. But converting a decimal to double never loses magnitude.

Related

How can I deal with this double.NaN

I have the a Convert.ToDecimal() which occasionally throws an exception with the message
Value was either too large or too small for a Decimal
, because the call to DataContainer.GetValue(ColKeyId, index) returns double.NaN.
if (Convert.ToDecimal(DataContainer.GetValue(ColKeyId, index)) != Convert.ToDecimal(newValueToSet))
{
DataContainer.SetValue(ColKeyId, index, newValueToSet);
}
I cannot change the API implementation call of the GetValue().
What would be the best approach to deal with the conversion to decimal of a NaN double?
Okay, so it sounds like you just need to detect whether or not it's a NaN value:
double value = DataContainer.GetValue(ColKeyId, index);
if (double.IsNaN(value) || double.IsInfinity(value) ||
(decimal) value != (decimal) newValueToSet)
{
DataContainer.SetValue(ColKeyId, index, newValueToSet);
}
To be honest, it's not clear why you're converting from double to decimal at all, but this code at least shows how you can detect NaN/infinite values. Note that I've changed the calls to Convert.ToDecimal to simple casts to make the code simpler - but you could use Convert.ToDecimal if you want, of course..
Decimal.TryParse
So then you will know if it converted or not and if not assigne a defasult value or branch off down some other avenue.
HTH
You can check if the value is double.NaN before setting:
if (!Double.IsNaN(DataContainer.GetValue(ColKeyId, index)))
{
if (Convert.ToDecimal(DataContainer.GetValue(ColKeyId, index)) != Convert.ToDecimal(newValueToSet))
{
DataContainer.SetValue(ColKeyId, index, newValueToSet);
}
}

Is there a C# equivalent to Java's Number class?

I'm new to C#, coming from Java, and I'd like to check whether a certain object is a Number (it can be an Integer, Double, Float, etc). In Java I did this by saying if (toRet instanceof Number). I'm hoping there's a similar C# thing like if (toRet is Number) but thus far I haven't been able to find a Number class that does this. Is there a way to do this, or do I have to manually check for Integer, Double, etc?
Edit for more info: Basically what I want to do is eventually have a byte array. However, when the array is stored in a text file, the parser I'm using can sometimes think it's an integer array or a double array. In Java, I had this:
JSONArray dblist = (JSONArray)result_;
byte[] reallyToRet = new byte[dblist.size()];
Object toComp = dblist.get(0);
if (toComp instanceof Number)
for (int i=0; i < dblist.size(); ++i) {
byte elem = ((Number) dblist.get(i)).byteValue();
reallyToRet[i] = elem;
}
return reallyToRet;
}
The important bit here is the if statement. Sometimes the objects in dblist would parse as integers, sometimes as doubles, and only rarely as bytes, but all I really care about at the end is the byte value.
Well, yeah, but it's an extension method that just ORs all the possibilities.
This is it:
public static bool IsNumber(this object value)
{
return value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is int
|| value is uint
|| value is long
|| value is ulong
|| value is float
|| value is double
|| value is decimal
|| value is BigInteger;
}
and you would use it like this:
if (toRet.IsNumber());
This needs to be in a static class.
I am not sure about any class for that. But you can check for instance, for integer see
int val;
if(Int32.TryParse(integer, out val))
else
Unlikely, you can use Double.TryParse(number, out val) etc.

Nullable double NaN comparison in C#

I have 2 nullable doubles, an expected value and an actual value (let's call them value and valueExpected). A percentage is found using 100 * (value / valueExpected). However, if valueExpected is zero, it returns NaN. Everything good so far.
Now, what do I do if I need to check the value, to see if it is NaN? Normally one could use:
if (!Double.IsNaN(myDouble))
But this doesn't work with nullable values (IsNaN only works with non-nullable variables). I have changed my code to do the check (valueExpected == 0), but I'm still curious - is there any way to check for a nullable NaN?
Edit: When I say the code doesn't work, I mean it won't compile. Testing for null first doesn't work.
With all Nullable<T> instances, you first check the bool HasValue property, and then you can access the T Value property.
double? d = 0.0; // Shorthand for Nullable<double>
if (d.HasValue && !Double.IsNaN(d.Value)) {
double val = d.Value;
// val is a non-null, non-NaN double.
}
You can also use
if (!Double.IsNaN(myDouble ?? 0.0))
The value in the inner-most parenthesis is either the myDouble (with its Nullable<> wrapping removed) if that is non-null, or just 0.0 if myDouble is null. Se ?? Operator (C#).
I had the same issue and I solved it with casting the double? with double
double.IsNaN((double)myDouble)
this will return true if NaN and false if not
With C# 7.0 Pattern matching combined null + NaN check check can be written like this:
double? d = whatever;
if(d is double val && double.IsNaN(val))
Console.WriteLine(val);
The advantage is local scoped variable val at hand, which is not null, nor double.NaN and can even be used outside of if.
With pattern matching in newer Roslyn C# versions, double.NaN is a valid pattern which tests using IsNaN (that is it works differently than Equals() where NaN is never equal to NaN as specified by IEEE floating point standard).
Therefore you can now do this:
double? myDouble = something;
if (myDouble is double and not double.NaN)
Console.WriteLine("A number");
For testing NaN this can even be shortened like this:
double? myDouble = something;
if (myDouble is double.NaN)
Console.WriteLine("Not a number and not NULL");

dividing efficiently

I want to divide a number of type double, by an int. I only need the result in 2 deicmal place in string format. What is the best way to do this in terms of stack efficiency?
double d=321321321313131233213213213213;
int i=123;
ToString(d/i); //what do I get when I do this? A double? A float?
public String ToString(float? result) //what should I cast the result?
{
return #String.Format("{0:#,0.##;} divided double by int", result);
}
ToString(d/i); //what do I get when I do this? A double? A float?
You'll get a double. Dividing a double by an int will result in a double value.
public String ToString(float? result) //what should I cast the result?
You'll get a double for the value, so you'd be better off just using a double here. You'll never get a nullable type, and definitely wouldn't get a float as a result, so using float? is wholly inappropriate.
What is the best way to do this in terms of stack efficiency?
This is really not worth worrying about, unless, of course, you profile and find this really happens to be a problem. Building the string will be far more expensive than the division operation, and neither is likely to be a hotspot in terms of performance.
A clean way to handle this would just be to use double.ToString("N2"), ie:
double result = d/i;
string resultAsString = result.ToString("N2");
If you want a full, formatted string, you can use:
string resultAsString = string.Format("{0:N2} divided double by int", result);
Ok. First off, you get double, not double? or float?. Math functions should never return a nullable type. If you are assuming that infinity is represented as null, you are wrong. Infinities are determined by the bits. You can see if a double is infinity with Double.IsInfinity(double).
[SecuritySafeCritical]
public static unsafe bool IsInfinity(double d)
{
return ((*(((long*) &d)) & 0x7fffffffffffffffL) == 0x7ff0000000000000L);
}
What is the best way to do this in terms of stack efficiency?
I would recommend a look at the tragedies of micro optimization over at Coding Horror.
As for the function. That is completely unnecessary. Your best bet is Double.ToString(...):
double val = d / i;
string result = val.ToString("N2");
However, if you are using String.Format(...), you can use:
double val = d / i;
string result = string.Format("{0:N2} divided double by int", val);
Hacky solution:
If you need only 2 decimal places, you can multiply your double by 100, convert it to an integer, and then divide it by i.
Now take the string of the result, and add a dot before the last two chars.
Don't forget to handle the edge cases of negative values and rounding problems.
If you really care about efficiency, division of fractions is a slow process in comparison to division of integers.

How to check for valid value before converting Decimal

I assume this will blow up if total is null (I don't recall if decimals are initalized to null at the beginning or zero)
public int SomePropertyName
{
get { return Convert.ToInt32(Decimal.Round(total)); }
}
So should I check for null or > 0 ?
Decimal is a value type - there's no such value as "null" for a decimal.
However, it's perfectly possible for a decimal to be out of range for an int. You might want:
decimal rounded = decimal.Round(total);
if (rounded < int.MinValue || rounded > int.MaxValue)
{
// Do whatever you ought to here (it will depend on your application)
}
return (int) rounded;
I'm somewhat confused as to why you're using Convert.ToInt32 at all though, given that your property is declared to return a decimal. What's the bigger picture here? What are you trying to achieve?
Decimal is a value type and can not be null.
If you need to know if it had been initialized, you should probably use a nullable decimal:
Decimal? total = null;
public int SomePropertyName
{
get
{
if (total.HasValue) Convert.ToInt32(Decimal.Round(total.Value));
return 0; // or whatever
}
}
Decimals are value types, and so cannot be null.
So no need to check there..
As others have said, Decimal is a value type and cannot be null. However, if converting from a string then Decimal.TryParse is your friend...
System.Decimal is a value type, so it cannot be null. Second thing, the method's return value is decimal, so why would you want to convert to a Int32?

Categories

Resources