What is the difference in C# between Convert.ToDecimal(string) and Decimal.Parse(string)?
In what scenarios would you use one over the other?
What impact does it have on performance?
What other factors should I be taking into consideration when choosing between the two?
There is one important difference to keep in mind:
Convert.ToDecimal will return 0 if it is given a null string.
decimal.Parse will throw an ArgumentNullException if the string you want to parse is null.
From bytes.com:
The Convert class is designed to
convert a wide range of Types, so you
can convert more types to Decimal than
you can with Decimal.Parse, which can
only deal with String. On the other
hand Decimal.Parse allows you to
specify a NumberStyle.
Decimal and decimal are aliases and
are equal.
For Convert.ToDecimal(string),
Decimal.Parse is called internally.
Morten Wennevik [C# MVP]
Since Decimal.Parse is called internally by Convert.ToDecimal, if you have extreme performance requirements you might want to stick to Decimal.Parse, it will save a stack frame.
One factor that you might not have thought of is the Decimal.TryParse method. Both Convert.ToDecimal and Parse throw exceptions if they cannot convert the string to the proper decimal format. The TryParse method gives you a nice pattern for input validation.
decimal result;
if (decimal.TryParse("5.0", out result))
; // you have a valid decimal to do as you please, no exception.
else
; // uh-oh. error message time!
This pattern is very incredibly awesome for error-checking user input.
One common suggestion related to original topic - please use TryParse() as soon as you not really sure that input string parameter WILL be correct number format representation.
Major Difference between Convert.ToDecimal(string) and Decimal.Parse(string)
is that Convert handles Null whereas the other throws an exception
Note: It won't handle empty string.
Convert.ToDecimal apparently does not always return 0. In my linq statement
var query = from c in dc.DataContext.vw_WebOrders
select new CisStoreData()
{
Discount = Convert.ToDecimal(c.Discount)
};
Discount is still null after converting from a Decimal? that is null. However, outside a Linq statement, I do get a 0 for the same conversion. Frustrating and annoying.
Knowing that Convert.ToDecimal is the way to go in most cases because it handles NULL, it, however, does not handle empty string very well. So, the following function might help:
'object should be a string or a number
Function ConvertStringToDecimal(ByVal ValueToConvertToDecimal As Object) As Decimal
If String.IsNullOrEmpty(ValueToConvertToDecimal.ToString) = False Then
Return Convert.ToDecimal(ValueToConvertToDecimal)
Else
Return Convert.ToDecimal(0)
End If
End Function
Related
Convert.ToInt32 behaves different when passed string vs float/double literal
var result = Convert.ToInt32(12.4);//returns 12
result = Convert.ToInt32(12.44);//returns 12
result = Convert.ToInt32(12.4444444);//returns 12
result = Convert.ToInt32("12.4"); // Input string was not in a correct format.
I understand different overloads of Convert.ToInt32 are being called for string and float/double
The question is why this inconsistent behavior shouldn't single overload for Convert.ToInt32 throw an exception for loss of precision ?
The question is why this inconsistent behavior shouldn't single
overload for Convert.ToInt32 throw an exception for loss of precision
?
You can think of the utility methods you're currently using to convert from double to int as "casting" i.e (int)12.4, (int)12.44 etc. which in essence means you for sure know that there is high chance that you'll lose data precision, thus in short is like telling the compiler "go ahead and convert it as I don't mind data loss", so, no exception will be thrown whereas the last example that converts from string to int should throw an exception because according to MSDN:
ToInt32(String) method is equivalent to passing value to the
Int32.Parse(String).
and as we all know Int32.Parse(String) throws an exception if the specified string is not in the correct format.
The way I see it, when you start with an float/double and you convert to int you expect a loss of precision. When you have a string that you convert to int you don't expect the parsing to do any losing of data, you just want it to parse and fail if the string is not valid.
You first have to convert your string into double, then cast it to int. or do another convert to int.
result = Convert.ToInt32(Convert.ToDouble("12.4"));
From msdn Convert.ToInt32(string)
Converts the specified string representation of a number to an equivalent 32-bit signed integer.
https://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.110).aspx
In given examples you can see that converting from double representation to int gives format exception.
so this is clearly by design. you should do it right.
This is so many times repeated at SO, but I would want to state my question explicitly.
How is a decimal which would look like 2.0100 "rightly" presented to the user as
another "decimal" 2.01?
I see a lot of questions on SO where the input is a string "2.0100" and need a decimal 2.01 out of it and questions where they need decimal 2.0100 to be represented as string "2.01". All this can be achieved by basic string.Trim, decimal.Parse etc. And these are some of the approaches followed:
decimal.Parse(2.0100.ToString("G29"))
Using # literal
Many string.Format options.
Various Regex options
My own one I used till now:
if (2.0100 == 0)
return 0;
decimal p = decimal.Parse(2.0100.ToString().TrimEnd('0'));
return p == 2.0100 ? p : 2.0100;
But I believe there has to be some correct way of doing it in .Net (at least 4) which deals with numeric operation and not string operation. I am asking for something that is not dealing with the decimal as string because I feel that ain't the right method to do this. I'm trying to learn something new. And would fancy my chances of seeing at least .1 seconds of performance gain since I'm pulling tens of thousands of decimal values from database :)
Question 2: If it aint present in .Net, which is the most efficient string method to get a presentable value for the decimal?
Edit: I do not just want a decimal to be presented it to users. In that case I can use it as a string. I do want it as decimal back. I will have to process on those decimal values later. So going by ToString approach, I first needs to convert it to string, and then again parse it to decimal. I am looking for something that doesn't deal with String class. Some option to convert decimal .20100 to decimal .201?
The "extra zeroes" that occur in a decimal value are there because the System.Decimal type stores those zeroes explicitly. For a System.Decimal, 1.23400 is a different value from 1.234, even though numerically they are equal:
The scaling factor also preserves any trailing zeroes in a Decimal number. Trailing zeroes do not affect the value of a Decimal number in arithmetic or comparison operations. However, trailing zeroes can be revealed by the ToString method if an appropriate format string is applied.
It's important to have the zeroes because many Decimal computations involve significant digits, which are a necessity of many scientific and high-precision calculations.
In your case, you don't care about them, but the appropriate answer is not "change Decimal for my particular application so that it doesn't store those zeroes". Instead, it's "present this value in a way that's meaningful to my users". And that's what decimal.ToString() is for.
The easiest way to format a decimal in a given format for the user is to use decimal.ToString()'s formatting options.
As for representing the value, 2.01 is equal to 2.0100. As long as you're within decimal's precision, it shouldn't matter how the value is stored in the system. You should only be worried with properly formatting the value for the user.
Numbers are numbers and strings are strings. The concept of "two-ness" represented as a string in the English language is 2. The concept of "two-ness" represented as a number is not really possibly to show because when you observe a number you see it as a string. But for the sake of argument it could be 2 or 2.0 or 02 or 02.0 or even 10/5. These are all representations of "two-ness".
Your database isn't actually returning 2.0100, something that you are inspecting that value with is converting it to a string and representing it that way for you. Whether a number has zeros at the end of it is merely a preference of string formatting, always.
Also, never call Decimal.parse() on a decimal, it doesn't make sense. If you want to convert a decimal literal to a string just call (2.0100).ToString().TrimEnd('0')
As noted, a decimal that internally stores 2.0100 could differ from one that stores 2.01, and the default behaviour of ToString() can be affected.
I recommend that you never make use of this.
Firstly, decimal.Parse("2.0100") == decimal.Parse("2.01") returns true. While their internal representations are different this is IMO unfortunate. When I'm using decimal with a value of 2.01 I want to be thinking:
2.01
Not:
struct decimal
{
private int flags;
private int hi;
private int lo;
private int mid;
/methods that make this actually useful/
}
While different means of storing 2.01 in the above structure might exist, 2.01 remains 2.01.
If you care about it being presented as 2.01 and not as 2.0 or 2.0100 then you care about a string representation. Your concern is about how a decimal is represented as a string, and that is how you should think about it at that stage. Consider the rule in question (minimum and maximum significant figures shown, and whether to include or exclude trailing zeros) and then code a ToString call appropriate.
And do this close to where the string is used.
When you care about 2.01, then deal with it as a decimal, and consider any code where the difference between 2.01 and 2.0100 matters to be a bug, and fix it.
Have a clear split in your code between where you are using strings, and where you are using decimals.
Ok, so I'm answering for myself, I got a solution.
return d / 1.00000000000000000000000000000m
That just does it. I did some benchmarking as well (time presented as comments are mode, not mean):
Method:
internal static double Calculate(Action act)
{
Stopwatch sw = new Stopwatch();
sw.Start();
act();
sw.Stop();
return sw.Elapsed.TotalSeconds;
}
Candidates:
return decimal.Parse(string.Format("{0:0.#############################}", d));
//0.02ms
return decimal.Parse(d.ToString("0.#############################"));
//0.014ms
if (d == 0)
return 0;
decimal p = decimal.Parse(d.ToString().TrimEnd('0').TrimEnd('.'));
return p == d ? p : d;
//0.016ms
return decimal.Parse(d.ToString("G29"));
//0.012ms
return d / 1.00000000000000000000000000000m;
//0.007ms
Needless to cover regex options. I dont mean to say performance makes a lot of difference. I'm just pulling 5k to 20k rows at a time. But still it's nice to know a simpler and cleaner alternative to string approach exists.
If you liked the answer, pls redirect your votes to here or here or here.
Console.WriteLine("Enter a double number");
string numberInput = Console.ReadLine();
double number = Double.Parse(numberInput)
My question is what is the last line of code doing? Is it doing the same thing as ToDouble?
The very short answer is:
Converts a string value into a double. e.g.
"2.3"(String) will become 2.3(double).
You have many choices on how to do this:
Double.TryParse()
Convert.ToDouble()
Double.TryParse() is handy if you don't know 100% that the input string is going to be a number value.
It is converts a string to double, the Console.ReadLine() methods read a string data and store it on string variable named numberInput, to convert from that string to double, Double.Parse is called we passing to it the numberInput string and it will convert it to double.
"Converts the string representation of a number in a specified style to its double-precision floating-point number equivalent."
See MSDN.
It's taking String input and interpreting it as numeric input - Double in this case. String and Double are quite different types. For one, mathematical operations can be performed on Double.
Converts the string representation of a number to its double-precision floating-point number equivalent.
MSDN: http://msdn.microsoft.com/en-us/library/system.double.parse.aspx
It's calling the Double.Parse method. According to the MSDN page it
Converts the string representation of a number to its double-precision floating-point number equivalent.
As per #DoctorMick's answer: It does the same thing as the Convert.ToDouble method.
In this case it's used because the code is getting a string from the user which can be thought of as a sequence of letters. We would want to get this into the proper type that we want to work with, which in this case is Double. Double has the parse method for this.
The data read into the variable numberInput is a string. The last line parses this into the type System.Double, so that it is better typed for other operations.
There is no guarantee that numberInput contains a valid numeric value, in which case the Parse method will throw an exception that you can catch.
There have been 7 different answers yet everyone seems to have overlooked the question of is it doing the same as ToDouble. The short answer is yet, it is doing the same, in fact ToDouble calls double.Parse internally.
While i am trying to convert a value to Int32, I get an error format exception, meaning the value is not in the proper format. I think I am converting a value in right format though.
Try using Int32.TryParse() you can find documentation on MSDN
You will get FormatException in cases such next:
Convert.ToInt32("foo");
Convert.ToInt32(5.5);
because
FormatException
value does not consist of an optional sign followed by a sequence of digits (0 through 9).
MSDN
string str = "123";
int i = 0;
if (int.TryParse(str, out i))
{
//do your logic here
}
Share your code here, you might missed something
Perhaps the hint is in "I think I am converting a value in right format though"
Are you sure your number is formatted according to your current culture?
If not, it's Int32.TryParse(String, NumberStyles, IFormatProvider, Int32%)
[details here][1] that you should be using
[1]: http://Int32.TryParse Method (String, NumberStyles, IFormatProvider, Int32%)
You can always check the type of the value you are passing in to such functions by using the GetType().
The condition where I was stuck in this issue was conversion of a dynamically generated stringyfied decimal value to int. Figured out the type of the value using the GetType() and first converting it into double then int solved the problem.
I am using Convert.ChangeType() to convert from Object (which I get from DataBase) to a generic type T. The code looks like this:
T element = (T)Convert.ChangeType(obj, typeof(T));
return element;
and this works great most of the time, however I have discovered that if I try to cast something as simple as return of the following sql query
select 3.2
the above code (T being double) wont return 3.2, but 3.2000000000000002. I can't realise why this is happening, or how to fix it. Please help!
What you're seeing is an artifact of the way floating-point numbers are represented in memory. There's quite a bit of information available on exactly why this is, but this paper is a good one. This phenomenon is why you can end up with seemingly anomalous behavior. A double or single should never be displayed to the user unformatted, and you should avoid equality comparisons like the plague.
If you need numbers that are accurate to a greater level of precision (ie, representing currency values), then use decimal.
This probably is because of floating point arithmetic. You probably should use decimal instead of double.
It is not a problem of Convert. Internally double type represent as infinite fraction of 2 of real number, that is why you got such result. Depending of your purpose use:
Either Decimal
Or use precise formating {0:F2}
Use Math.Flor/Math.Ceil