decimal.ToString behaviour

G

Guest

I have come across a behaviour with the decimal.ToString method which i didn't expect, if i run the following console ap
using System

public class Ap

public static void Main(string[] args

decimal _decValue
foreach(string _arg in args

_decValue = decimal.Parse(_arg);
Console.WriteLine(_decValue.ToString())




with the following arg
1 1.00 1.000

I will get output as follow
1
1.00
1.000

I would have expecte




Can't see anything in the SDK explaining this. If anyone knows why this is so i would appreciate a pointer

Thanks in advanc
Pa
 
P

Peter van der Goes

PM said:
I have come across a behaviour with the decimal.ToString method which i
didn't expect, if i run the following console app
using System;

public class App
{
public static void Main(string[] args)
{
decimal _decValue;
foreach(string _arg in args)
{
_decValue = decimal.Parse(_arg);
Console.WriteLine(_decValue.ToString());
}
}
}

with the following args
1 1.00 1.0000

I will get output as follows
1
1.00
1.0000

I would have expected
1
1
1

Can't see anything in the SDK explaining this. If anyone knows why this is
so i would appreciate a pointer.
Thanks in advance
Pat

It's the behavior of the Parse() method, not ToString() that may be
surprising to you. Parse() has no powers of interpretation, and just takes
the input character by character and converts it (in your case) to decimal
storage until either a) the end of the input string is reached, or b) an
inappropriate character is encountered (in which case, an exception is
thrown). So, "1.000" is converted to the exact decimal equivalent.
ToString() converts what it finds back to string representation, again
without making any judgments about what is worth keeping.
I guess I'd have to say that I'd find any other behavior from Parse() and
ToString() a bit surprising.
 
J

Jon Skeet [C# MVP]

Peter van der Goes said:
I guess I'd have to say that I'd find any other behavior from Parse() and
ToString() a bit surprising.

Then you'd have been surprised by 1.0. It was only with 1.1 that
decimal started retaining trailing zeroes.
 
D

Daniel Billingsley

But you'd agree the new behavior is better, wouldn't you? I mean, 1 is
technically not an accurate representation of 1.000, is it?
 
J

Jon Skeet [C# MVP]

Daniel Billingsley said:
But you'd agree the new behavior is better, wouldn't you? I mean, 1 is
technically not an accurate representation of 1.000, is it?

Indeed I can see the reason that the new behaviour is better, but I
certainly found it a surprise, if only because it's a significant
difference between binary floating point types (Single and Double) and
the decimal floating point type (Decimal).

I'm also surprised that there isn't a Normalize method which converts
1.000 to 1, etc. I would imagine that comparing normalized
representations would be significantly faster (as you could just
compare bit patterns), so in an app which did a lot of decimal
comparisons, it would be handy to be able to get to the normalized form
(and to have a comparison which was precision-sensitive, i.e. just
compared bit patterns). Writing such routines isn't particularly hard,
but it's something I'd expect the framework to come with. Then again, I
think it would be handy for Double to have a method which returned the
*exact* value as a string, too...
 
P

Peter van der Goes

Jon Skeet said:
Then you'd have been surprised by 1.0. It was only with 1.1 that
decimal started retaining trailing zeroes.

I'm confused by your comment, John.
I passed the following arguments to the OP's code:
"1"
"1.000"
"1.00000"
"1.1"
"1.100"
Each string converted using decimal.Parse(), then reconverted for display
using ToString().
In all cases, the output was identical to the input string.
Seems to work the same way regardless. What am I missing?
 
P

Peter van der Goes

Jon Skeet said:
Then you'd have been surprised by 1.0. It was only with 1.1 that
decimal started retaining trailing zeroes.

My apologies for the previous response. I was having a dumba** moment and
thought you were referring to values, not .NET Framework versions.
You're correct. I would have been surprised by the 1.0 behavior.
 
J

Jon Skeet [C# MVP]

Peter van der Goes said:
My apologies for the previous response. I was having a dumba** moment and
thought you were referring to values, not .NET Framework versions.
You're correct. I would have been surprised by the 1.0 behavior.

Would you also be surprised by Double.Parse("0.500").ToString() just
returning "0.5" out of interest?
 
P

Peter van der Goes

Jon Skeet said:
Would you also be surprised by Double.Parse("0.500").ToString() just
returning "0.5" out of interest?

OK, OK. You win, John. This seems (to me at any rate) to be inconsistent.
I'm not surprised by anything at this stage. The double.Parse() method
appears to do things differently.
Now I'm confused :)
 
J

Jon Skeet [C# MVP]

Peter van der Goes said:
OK, OK. You win, John. This seems (to me at any rate) to be inconsistent.

It is inconsistent in terms of comparing binary floating point with
decimal floating point, but it's consistent in terms of how the rest of
the world tends to do binary and decimal floating point.
I'm not surprised by anything at this stage. The double.Parse() method
appears to do things differently.
Now I'm confused :)

The difference is that decimal isn't normalised, and float/double are.
Have a look at http://www.pobox.com/~skeet/csharp/floatingpoint.html
and http://www.pobox.com/~skeet/csharp/decimal.html for more
information.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top