How can I deal with this double.NaN - c#

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);
}
}

Related

Test whether a decimal value can be converted to double

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.

Novice enquiry on using TryParse() properly

I've just tried TryParse, and am new to C# and just trying to understand everything, and then hopefully best practices...
Syntactically this works:
double number = Double.Parse(C.ReadLine());
Does TryParse only return a boolean, true if parse succeeds?
When I do this:
double number;
bool b = Double.TryParse(C.ReadLine(), out number);
number is the parsed input, from C.ReadLine(), as expected, everything works. Is this how TryParse is normally used? Trying to be efficient, appreciate advice like this.
Any advice on approach welcome, plus info on online resources for Try(things).
You use TryParse when it may fail, and you don't want your code to throw an exception.
For example
if (!Double.TryParse(someinput, out number))
{
Console.WriteLine("Please input a valid number");
}
Parse will return the double value if it succeeds and throws an exception otherwise. TryParse will return a boolean value representing the success of the operation and if it does succeed, it fills in the parsed value in the out argument you pass to it. It will never throw an exception.
In general, you should use TryParse when you expect the input string to not be a valid number and you have the logic to handle it (and display an error message, for instance).
If you don't expect the input string to be anything except a valid double you should use Parse.
The only differnce is that TryParse won't thow an exception if it can't parse the double.
This is handy when you want to assign a default value or ignore the value in your code
Example:
double number;
if (Double.TryParse(C.ReadLine(), out number))
{
// this is a double so all good
}
else
{
// not a valid double.
}
Example:
double number;
progressBar.Value = Double.TryParse(C.ReadLine(), out number) ? number : 4.0;
// If number is a valid double, set progressbar, esle set default value of 4.0
You also asked aboy TyrParse on Enum, this can be done like this
DayOfWeek fav;
if (Enum.TryParse<DayOfWeek>(Console.ReadLine(), out fav))
{
// parsed
}

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");

Understanding the null coalescing operator (??)

I have a custom WebControl which implements a .Value getter/setter returning a Nullable<decimal>
It's a client-side filtered textbox (a subclass of TextBox with included javascript and some server side logic for setting/getting the value)
Here is the getter & the setter from that control:
public decimal? Value
{
get
{
decimal amount = 0;
if (!decimal.TryParse(this.Text, NumberStyles.Currency, null, out amount))
{
return null;
}
else
{
return amount;
}
}
set
{
if (!value.HasValue)
{
this.Text = "";
}
else
{
this.Text = string.Format("${0:#,##0.00}", value);
}
}
}
The problem that I'm seeing is that the output from this statement:
decimal Amount = uxAmount.Value ?? 0M;
I am seeing Amount being set to "0" when uxAmount.Value returns 10000.
This worked as I expected (excuse the change in casing):
decimal? _Amount = uxAmount.Value;
decimal amount = _Amount ?? 0;
I have also seen this behaviour (recently) when calling a UDF function defined on a Linq2Sql data context along with the null coalescing operator, that is I knew my UDF call returned the expected value but I was getting the RHS value instead.
Further confusing me, if I evaluate uxAmount.Value in the watch, I get 10000 of type Nullable<decimal>.
Here are some expressions I've tried:
decimal? _Amount = uxAmount.Value; //10000
decimal amount = _Amount ?? 0; //10000
decimal amount2 = _Amount ?? 0M; //10000
decimal Amount = uxAmount.Value ?? 0M; //0
Then I added this expression following the above 4
decimal amount3 = (uxTaxAmount.Value) ?? 0M;
Now
decimal Amount = uxAmount.Value ?? 0M; //10000
decimal amount3 = (uxAmount.Value) ?? 0M; //0
It seems like the last call is always 0, but the value of uxAmount.Value (which is parsed out of .Text as per above getter/setter using a TryParse is stable. I'm stopped at a breakpoint and there's no other threads that could manipulate this value.
Note the use of the M suffix to force the constant to decimal as it was integer and I suspected a type conversion issue.
Any ideas?
The value of both the LHS and RHS appear to be stable and known.
--edit-- some screengrabs from VS2010
(This answer was constructed from my comments above.)
Are you sure the debugger dsiplays this correctly to you? Have you tried stepping some lines further down to make sure you have the updated value of amount3?
I'm sure it's just an issue with the debugger. Sometimes you have to step a little further. Maybe the translated code (IL) has some optimizations that confuse the debugger (or what would I know). But without the debugger, the value will be updated exactly when you expect it.
I've seen other experienced developers being confused by similar situations, so I know the debugger sometimes is "one line of code" behind when looking at an assignment to a local variable. Maybe someone can find a link discussing that?
Take a look at this similar question
using coalescing null operator on nullable types changes implicit type
why not just do
decimal amount = uxTaxAmount.Value.HasValue ? uxTaxAmount.Value.Value : 0M
This isn't the right answer to the original posters problems given recent edits and comments.

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