Connecting Tech Pros Worldwide Help | Site Map

Odd behaviour with Decimal.ToString

Oenone
Guest
 
Posts: n/a
#1: Nov 23 '05
Can anyone explain why the following happens?

\\\
Dim d1 As Decimal = CDec("100")
Dim d2 As Decimal = CDec("100.00")

MsgBox(d1.ToString) 'displays "100"
MsgBox(d2.ToString) 'displays "100.00"

MsgBox(d1 = d2) 'displays "True"
///

How are the Decimal variables remembering the fact that I provided the two
decimal places for d2, but not for d1? I can't see any properties of the
Decimal structure that would allow it to do this...

Thanks,

--

(O)enone


Peter Proost
Guest
 
Posts: n/a
#2: Nov 23 '05

re: Odd behaviour with Decimal.ToString


I think it has to do with having . set as decimal seperator and , grouping
symbol in your regional settings
Because with me 100 = 100.00 = false
but 100 = 100,00 = true because I've my decimal seperator = , and grouping
symbol = .
If I set . as decimal seperator and , as grouping symbol then 100 = 100.00
= true
and 100 = 100,00 = false

hth

Greetz Peter

--
Programming today is a race between software engineers striving to build
bigger and better idiot-proof programs, and the Universe trying to produce
bigger and better idiots. So far, the Universe is winning. (Rich Cook)

"Oenone" <oenone@nowhere.com> schreef in bericht
news:OWaIFeS5FHA.268@TK2MSFTNGP10.phx.gbl...[color=blue]
> Can anyone explain why the following happens?
>
> \\\
> Dim d1 As Decimal = CDec("100")
> Dim d2 As Decimal = CDec("100.00")
>
> MsgBox(d1.ToString) 'displays "100"
> MsgBox(d2.ToString) 'displays "100.00"
>
> MsgBox(d1 = d2) 'displays "True"
> ///
>
> How are the Decimal variables remembering the fact that I provided the two
> decimal places for d2, but not for d1? I can't see any properties of the
> Decimal structure that would allow it to do this...
>
> Thanks,
>
> --
>
> (O)enone
>
>[/color]


Oenone
Guest
 
Posts: n/a
#3: Nov 23 '05

re: Odd behaviour with Decimal.ToString


Peter Proost wrote:[color=blue]
> I think it has to do with having . set as decimal seperator and ,
> grouping symbol in your regional settings[/color]

Ah sorry, I should have been clearer with that -- I do indeed have "." as
decimal and "," as thousands separators (UK regional settings).

But that wasn't the question I was asking -- the question was how and why
the Decimal variable stores the fractional part of the value when all of the
fractional digits were zero. How does the Decimal variable distinguish
between me storing "100.00" and "100"? I would have expected
Decimal.ToString to return "100" in both cases, just like a Double variable
does.

--

(O)enone


Peter Proost
Guest
 
Posts: n/a
#4: Nov 23 '05

re: Odd behaviour with Decimal.ToString


It seems normal behavior to me, but to the how and why I can't realy give
you an answer. To only thing I could find in the msdn help is:

Decimal.ToString Method (String) [Visual Basic]

Remarks
If format is a null reference (Nothing in Visual Basic) or an empty string,
the return value of this instance is formatted with the general format
specifier ("G").

Hth Greetz Peter

--
Programming today is a race between software engineers striving to build
bigger and better idiot-proof programs, and the Universe trying to produce
bigger and better idiots. So far, the Universe is winning. (Rich Cook)

"Oenone" <oenone@nowhere.com> schreef in bericht
news:#pdJtCT5FHA.3292@tk2msftngp13.phx.gbl...[color=blue]
> Peter Proost wrote:[color=green]
> > I think it has to do with having . set as decimal seperator and ,
> > grouping symbol in your regional settings[/color]
>
> Ah sorry, I should have been clearer with that -- I do indeed have "." as
> decimal and "," as thousands separators (UK regional settings).
>
> But that wasn't the question I was asking -- the question was how and why
> the Decimal variable stores the fractional part of the value when all of[/color]
the[color=blue]
> fractional digits were zero. How does the Decimal variable distinguish
> between me storing "100.00" and "100"? I would have expected
> Decimal.ToString to return "100" in both cases, just like a Double[/color]
variable[color=blue]
> does.
>
> --
>
> (O)enone
>
>[/color]


Andrew Morton
Guest
 
Posts: n/a
#5: Nov 23 '05

re: Odd behaviour with Decimal.ToString


Oenone wrote:[color=blue]
> How are the Decimal variables remembering the fact that I provided
> the two decimal places for d2, but not for d1? I can't see any
> properties of the Decimal structure that would allow it to do this...[/color]

From the help:-
"Decimal variables are stored as signed 128-bit (16-byte) integers scaled by
a variable power of 10. The scaling factor specifies the number of digits to
the right of the decimal point"

So you have a case of scaling factor being 0 or 2.

Andrew


Oenone
Guest
 
Posts: n/a
#6: Nov 23 '05

re: Odd behaviour with Decimal.ToString


Andrew Morton wrote:[color=blue]
> From the help:-[/color]
[...]

Ah, that'll teach me to read before posting questions. :)

Many thanks for your reply, that explains what I'm seeing.

--

(O)enone


Larry Lard
Guest
 
Posts: n/a
#7: Nov 23 '05

re: Odd behaviour with Decimal.ToString



Oenone wrote:[color=blue]
> Can anyone explain why the following happens?
>
> \\\
> Dim d1 As Decimal = CDec("100")
> Dim d2 As Decimal = CDec("100.00")
>
> MsgBox(d1.ToString) 'displays "100"
> MsgBox(d2.ToString) 'displays "100.00"
>
> MsgBox(d1 = d2) 'displays "True"
> ///
>
> How are the Decimal variables remembering the fact that I provided the two
> decimal places for d2, but not for d1? I can't see any properties of the
> Decimal structure that would allow it to do this...[/color]

This was pretty interesting! For the short answer, set a breakpoint on
a msgbox and note the difference in output here (GetBits is what we use
when we find that BitConverter.GetBytes doesn't accept a Decimal...)

?system.decimal.getbits(d1)
{Length=4}
(0): 100
(1): 0
(2): 0
(3): 0
?system.decimal.getbits(d2)
{Length=4}
(0): 10000
(1): 0
(2): 0
(3): 131072

Now the reason .Equals (which is what = gets compiled to) returns true
is because these two values do both represent the same value (exactly
100) but as you can see, internally they have different
representations!
[color=blue]
>From the help:[/color]
[color=blue][color=green]
>>[/color][/color]
A decimal number is a signed, fixed-point value consisting of an
integral part and an optional fractional part. The integral and
fractional parts consist of a series of digits that range from zero to
nine (0 to 9), separated by a decimal point symbol.

The binary representation of an instance of Decimal consists of a 1-bit
sign, a 96-bit integer number, and a scaling factor used to divide the
96-bit integer and specify what portion of it is a decimal fraction.
The scaling factor is implicitly the number 10, raised to an exponent
ranging from 0 to 28.[color=blue][color=green]
>>[/color][/color]

So without poking around too much, we can surmise that CDec("100") gets
you a decimal which is stored as 100 * 10^0, but CDec("100.00") gets
you a decimal which is stored as 10000 * 10^-2. And a plain vanilla
..ToString just dumps out the internal representation.

The lesson? Always specify a format for outputting Decimals, I suppose.

--
Larry Lard
Replies to group please

Oenone
Guest
 
Posts: n/a
#8: Nov 23 '05

re: Odd behaviour with Decimal.ToString


Larry Lard wrote:[color=blue]
> This was pretty interesting![/color]

Thanks very much for your detailed reply, always nice to find more about the
internal workings of VB.NET.
[color=blue]
> The lesson? Always specify a format for outputting Decimals, I
> suppose.[/color]

The code I was trying to write was a generic piece of code that builds XML,
and ultimately compares the XML as a string against another piece of XML, so
I couldn't put any formatting into the ToString() call as I didn't know what
format to use. I resolved it by converting the Decimal to a Double, and then
calling the ToString() method on that. That returns the numbers with no
unnecessary decimal places regardless of how the value was originally
specified.

--

(O)enone



Closed Thread