471,325 Members | 1,824 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,325 software developers and data experts.

Let no good deed go unpunished--why you can't be too careful with C#DecimalParse NumberStyles

Here is a classic example of why C# is like beating your head against
the wall. I can tell you where the error is in the below code--it's
the "NumberStyles" property of DecimalParse (which extracts a decimal
from a string)--and how to fix it--you leave it out--but why? WHY?
Y?

We'll never know... that's just the way it is. Some things were meant
to be...

(PS--my debugger is horrible--it doesn't usually work--but if I were
to 'guess' the problem it would be the NumberStyles flags comprise
more than one flag and they are "OR'd" together. As you logic freaks
know, when you "OR" more than two logical flags, you get potential
problems. BUT, I have to point out I got this from MSDN, which had
this example (four flags) AND, no pun intended, you would think they
would have the flags done right so that you can use more than two
flags at the same time. UPDATE: I just tried it with one flag, two
flags and it still fails for the NumberStyles version)

Below is the complete code, cut and paste and it should work to demo
the problem.

See the comments for where the 'error' is. I also am using a
NumberStyles I got from MSDN Help--so it should have worked--but did
not.

Here is the MSDN link for TryParse (similar to Decimal Parse):
http://msdn.microsoft.com/en-us/library/zf50za27.aspx
And here for NumberStyles: http://msdn.microsoft.com/en-us/libr...berstyles.aspx

RL

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;

namespace Console1
{
class Program
{
static void Main(string[] args)
{
NumberStyles styles = NumberStyles.AllowParentheses |
NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite |
NumberStyles.AllowTrailingWhite;

//PLAIN GENERIC NUMBERSTYLES! WHY DOES C# HAVE TO BE SO DIFFICULT,
WHY, why, Y?

string s1 = "1.23";

decimal d1 = DecimalParse(styles, s1);

Console.WriteLine("s1, d1 are: {0}, {1}", s1, d1); //try
fails, catch thrown. you get d1=0.99 in decimal returned, indicating
the catch block was executed

//now leave out NumberStyles--and see what happens (it works)

decimal d2 = DecimalParse2(s1);

Console.WriteLine("s1, d2: {0}, {1}", s1, d2); //you get
d2=1.23 in decimal returned, correct.
// output:
/*
* parse failed: Input string was not in a correct
format.s1, d1 are: 1.23, 0.99
* s1, d2: 1.23, 1.23
* Press any key to continue . . .
*
* */

// just for shi it s and grins, see if a non-static version makes a
difference (it does not, as I expected)

Program myProgram = new Program();

decimal aDecimal;

aDecimal = myProgram.nonStatic_DecimalParse(styles, s1);

Console.WriteLine("s1, aDecimal for non-static
DecimalParse: {0}, {1}", s1, aDecimal);
// still fails, like first static example above

//now should succeed, if you leave out NumberStyles

aDecimal = myProgram.nonStatic_DecimalParse2(s1);
Console.WriteLine("s1, aDecimal for non-static
DecimalParse2: {0}, {1}", s1, aDecimal);
//yes, succeeds to give 1.23, 1.23 as wanted
}

static decimal DecimalParse(NumberStyles styles, string
decimalString)
{
try
{
decimal decimalNumber;

decimalNumber = Decimal.Parse(decimalString, styles);
Debug.Write("decimalNumber is: " +
decimalNumber.ToString());
return decimalNumber;

}
catch (Exception ex)
{
// Display the exception message if Parse failed
Console.Write("parse failed: " + ex.Message);
return 0.99M;
}
} //

// leaving out NumberStyles version of method here:

static decimal DecimalParse2(string decimalString)
{
try
{
decimal decimalNumber;

decimalNumber = Decimal.Parse(decimalString);
return decimalNumber;

}
catch (Exception ex)
{
// Display the exception message if Parse failed
Console.Write("parse failed: " + ex.Message);
return 0.69M;
}
} //

decimal nonStatic_DecimalParse(NumberStyles styles, string
decimalString)
{
try
{
decimal decimalNumber;

decimalNumber = Decimal.Parse(decimalString, styles);
Debug.Write("decimalNumber is: " +
decimalNumber.ToString());
return decimalNumber;

}
catch (Exception ex)
{
// Display the exception message if Parse failed
Console.Write("parse failed: " + ex.Message);
return 0.99M;
}
} //

decimal nonStatic_DecimalParse2(string decimalString)
{
try
{
decimal decimalNumber;

decimalNumber = Decimal.Parse(decimalString);
return decimalNumber;

}
catch (Exception ex)
{
// Display the exception message if Parse failed
Console.Write("parse failed: " + ex.Message);
return 0.69M;
}
} //
}
}

Sep 2 '08 #1
22 1452
aylopez99 <ra********@yahoo.comwrote:
Here is a classic example of why C# is like beating your head against
the wall.
No, it's an example of the .NET framework not working the way you want
it to. As I've said before, it's important to distinguish between the
language and the framework. C# as a language doesn't know anything
about NumberStyles.

<snip>

Here's a short but complete program showing the actual problem. I had
to do various bits of fixing with your original code due to line
wrapping. It's generally worth posting programs with no lines longer
than 78 characters.

using System;
using System.Globalization;

class Program
{
static void Main(string[] args)
{
NumberStyles styles = NumberStyles.AllowParentheses |
NumberStyles.AllowLeadingSign |
NumberStyles.AllowLeadingWhite |
NumberStyles.AllowTrailingWhite;

decimal.Parse("1.23", styles);
}
}

It's *much* clearer to just present a program as short as the above and
say, "This is throwing a System.FormatException with the message 'Input
string was not in a correct format' and I don't know why," than to
include the kind of massive program you did.

Now for the actual problem... fix is simple: include
NumberStyles.AllowDecimalPoint.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 2 '08 #2
raylopez99 wrote:
Here is a classic example of why C# is like beating your head against
the wall.
You seem to be good at that head beating thing... ;) and once again
there is nothing wrong with the programming language...
I can tell you where the error is in the below code--it's
the "NumberStyles" property of DecimalParse (which extracts a decimal
from a string)--and how to fix it--you leave it out--but why? WHY?
Y?
Because it's incorrect.
We'll never know... that's just the way it is. Some things were meant
to be...
Well, Jon spotted the problem right away, so now we know...
(PS--my debugger is horrible--it doesn't usually work--but if I were
to 'guess' the problem it would be the NumberStyles flags comprise
more than one flag and they are "OR'd" together. As you logic freaks
know, when you "OR" more than two logical flags, you get potential
problems.
Why do you think that? What potential problems could possibly come from
or:ing more than two values?
BUT, I have to point out I got this from MSDN, which had
this example (four flags) AND, no pun intended, you would think they
would have the flags done right so that you can use more than two
flags at the same time. UPDATE: I just tried it with one flag, two
flags and it still fails for the NumberStyles version)
You obviously took the flags from an example that was parsing an integer
value. If you take example code intended for one purpose and use it for
something different without considering that it may need adjusting,
there is no surprise that it doesn't work as you expect.
Below is the complete code, cut and paste and it should work to demo
the problem.

See the comments for where the 'error' is. I also am using a
NumberStyles I got from MSDN Help--so it should have worked--but did
not.

Here is the MSDN link for TryParse (similar to Decimal Parse):
http://msdn.microsoft.com/en-us/library/zf50za27.aspx
And here for NumberStyles: http://msdn.microsoft.com/en-us/libr...berstyles.aspx

RL
8< snip another bloated piece of example code...

--
Göran Andersson
_____
http://www.guffa.com
Sep 2 '08 #3
The Decimal.TryParse example would have been better for you to follow. It
includes the AllowDecimal flag that Jon points out you need. I would assume
this is included in the default mode, where you omitted the NumberStyles,
and hence it worked. After all, what's the point of the Decimal type
without a decimal...

"raylopez99" <ra********@yahoo.comwrote in message
news:e9**********************************@y38g2000 hsy.googlegroups.com...
>
Here is the MSDN link for TryParse (similar to Decimal Parse):
http://msdn.microsoft.com/en-us/library/zf50za27.aspx
And here for NumberStyles:
http://msdn.microsoft.com/en-us/libr...berstyles.aspx

RL
Sep 2 '08 #4
"Family Tree Mike" <Fa************@ThisOldHouse.comwrote in message
news:uO**************@TK2MSFTNGP04.phx.gbl...
After all, what's the point of the Decimal type without a decimal...
Having 28 digits can be useful at times even if you don't bother with the
fractional part.
Sep 3 '08 #5
On Sep 2, 4:16*pm, "Family Tree Mike"
<FamilyTreeM...@ThisOldHouse.comwrote:
The Decimal.TryParse example would have been better for you to follow. *It
includes the AllowDecimal flag that Jon points out you need. *I would assume
this is included in the default mode, where you omitted the NumberStyles,
and hence it worked. *After all, what's the point of the Decimal type
without a decimal...
I assumed that the default would include "AllowDecimal", in other
words, that the flags would be more inclusive rather than all-
inclusive.

I was wrong.

Thanks for your help, and sorry to bother you.

In fact, in the actual program, I got rid of these NumberStyles, and
instead depend on an ErrorProvider component to kick in during
Validating event of the forms to catch any errors as the user types
them--much clearer to me, and easier to code.

RL

Sep 3 '08 #6
On Sep 2, 4:07*pm, Göran Andersson <gu...@guffa.comwrote:
Why do you think that? What potential problems could possibly come from
or:ing more than two values?

Well, what is the result of this:

X AND Y AND Z

where X,Y,Z are 0 or 1 (so you have nine combinations)

consider:

(X AND Y) AND Z

versus

(X) AND (Y AND Z)

versus

X AND Y AND Z

I think it makes a difference. Same for OR, but to a lesser degree
(if at all). Same for XOR. That's why I don' combine more than two
flags at a time.

RL
Sep 3 '08 #7
On Sep 3, 10:57*am, raylopez99 <raylope...@yahoo.comwrote:
On Sep 2, 4:07*pm, Göran Andersson <gu...@guffa.comwrote:
Why do you think that? What potential problems could possibly come from
or:ing more than two values?

Well, what is the result of this:

X AND Y AND Z

where X,Y,Z are 0 or 1 (so you have nine combinations)

consider:

(X AND Y) AND Z

versus

(X) AND (Y AND Z)

versus

X AND Y AND Z

I think it makes a difference.
Then please show an example. It really doesn't - ditto with OR.

There *is* a difference between
(X OR Y) AND Z
X OR (Y AND Z)
but that's a different matter.

For each bit position, X OR Y OR Z the bit will be set if *any of* X,
Y or Z have that bit set, regardless of bracketing.

For each bit position, X AND Y AND Z the bit will be set if *all of*
X, Y and Z have that bit set, regardless of bracketing.

If bit flags didn't allow more a combination of more than 2
possibilities, they'd be nearly useless.

Jon
Sep 3 '08 #8
On Sep 3, 2:57*am, raylopez99 <raylope...@yahoo.comwrote:
Well, what is the result of this:

X AND Y AND Z

where X,Y,Z are 0 or 1 (so you have nine combinations)
Actually, I made a mistake: it's 27 combinations (3x3x3), some of
which are symmetrical and repeat, but it's a lot of combinations, more
than nine.

RL
Sep 3 '08 #9
On Sep 3, 11:17*am, raylopez99 <raylope...@yahoo.comwrote:
On Sep 3, 2:57*am, raylopez99 <raylope...@yahoo.comwrote:
Well, what is the result of this:
X AND Y AND Z
where X,Y,Z are 0 or 1 (so you have nine combinations)

Actually, I made a mistake: *it's 27 combinations (3x3x3), some of
which are symmetrical and repeat, but it's a lot of combinations, more
than nine.
No, there are 8. If each of X, Y or Z can be 0 or 1, so there are 2 to
the power of 3 combinations. Here they all are, including the result
for X AND Y AND Z:

X Y Z (X AND Y AND Z)
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 0
1 1 1 1

Jon
Sep 3 '08 #10
raylopez99 wrote:
On Sep 2, 4:07 pm, Göran Andersson <gu...@guffa.comwrote:
>Why do you think that? What potential problems could possibly come
from or:ing more than two values?


Well, what is the result of this:

X AND Y AND Z

where X,Y,Z are 0 or 1 (so you have nine combinations)

consider:

(X AND Y) AND Z

versus

(X) AND (Y AND Z)

versus

X AND Y AND Z

I think it makes a difference. Same for OR, but to a lesser degree
(if at all). Same for XOR. That's why I don' combine more than two
flags at a time.
Simple rule for a string of ANDs -- if any value is <falsethe result
is <false>.

Simple rule for a string of ORs -- if any value is <true the result
is <true>.
Google "Boolean algebra laws". You'll find several good explanations.
Once you understand the laws you'll be able to answer questions such
as this easily.

--
--
--John
to email, dial "usenet" and validate
(was jclarke at eye bee em dot net)
Sep 3 '08 #11
I hadn't had that need come up yet, but it makes sense. Thanks for the
advice!

"Pavel Minaev" <in****@gmail.comwrote in message
news:Ok*************@TK2MSFTNGP05.phx.gbl...
"Family Tree Mike" <Fa************@ThisOldHouse.comwrote in message
news:uO**************@TK2MSFTNGP04.phx.gbl...
>After all, what's the point of the Decimal type without a decimal...

Having 28 digits can be useful at times even if you don't bother with the
fractional part.

Sep 3 '08 #12
J. Clarke wrote:
consider:

(X AND Y) AND Z

versus

(X) AND (Y AND Z)

versus

X AND Y AND Z

I think it makes a difference.
No, it doesn't:

X Y Z (x & y) & z x & (y & z)

0 0 0 0 & 0 = 0 0 & 0 = 0
1 0 0 0 & 0 = 0 1 & 0 = 0
0 1 0 0 & 0 = 0 0 & 0 = 0
1 1 0 1 & 0 = 0 1 & 0 = 0
0 0 1 0 & 1 = 0 0 & 1 = 0
1 0 1 0 & 1 = 0 1 & 0 = 0
0 1 1 0 & 1 = 0 0 & 1 = 0
1 1 1 1 & 1 = 1 1 & 1 = 1

No matter how many ANDs there are, the result is only 1 if ALL inputs
are 1 (i.e. if X = 1 and Y = 1 and Z = 1). Similarly for OR: the result
is only 0 if all inputs are 0 (i.e. if X = 0 and Y = 0 and Z = 0).

--
Rudy Velthuis http://rvelthuis.de

"#3 pencils and quadrille pads."
-- Seymoure Cray (1925-1996) when asked what CAD tools he used
to design the Cray I supercomputer; he also recommended using
the back side of the pages so that the lines were not so
dominant.
Sep 3 '08 #13
On Sep 3, 5:06*am, "J. Clarke" <jclarke.use...@cox.netwrote
Simple rule for a string of ANDs -- if any value is <falsethe result
is <false>.

Simple rule for a string of ORs *-- if any value is <true*the result
is <true>.

Google "Boolean algebra laws". *You'll find several good explanations.
Once you understand the laws you'll be able to answer questions such
as this easily.
Karnough map and DeMorgan's theorem comes to mind. Yeah I think
you're right. Anyway, flags have to be set up so that they obey
Boolean Algebra--otherwise these neat logical symmetries don't work.
That's why flag enumerations are or should be in powers of two.

RL
Sep 3 '08 #14
On Sep 3, 5:22*am, "Rudy Velthuis" <newsgro...@rvelthuis.dewrote:
* 0 *0 *0 * * 0 & 0 = 0 * * 0 & 0 = 0
* 1 *0 *0 * * 0 & 0 = 0 * * 1 & 0 = 0
* 0 *1 *0 * * 0 & 0 = 0 * * 0 & 0 = 0
* 1 *1 *0 * * 1 & 0 = 0 * * 1 & 0 = 0
* 0 *0 *1 * * 0 & 1 = 0 * * 0 & 1 = 0
* 1 *0 *1 * * 0 & 1 = 0 * * 1 & 0 = 0
* 0 *1 *1 * * 0 & 1 = 0 * * 0 & 1 = 0
* 1 *1 *1 * * 1 & 1 = 1 * * 1 & 1 = 1

No matter how many ANDs there are, the result is only 1 if ALL inputs
are 1 (i.e. if X = 1 and Y = 1 and Z = 1). Similarly for OR: the result
is only 0 if all inputs are 0 (i.e. if X = 0 and Y = 0 and Z = 0).

Thanks. Of course you're right, but in a real world AND, OR, NOR,
NAND you would have setup and hold problems so that X&Y would not
equal Y&X if outside the specified setup/hold times, but I'm just
being a smart aleck. So if X&Y != Y&X, then you do have 27 triplets,
and I was "right all along".

RL

Sep 3 '08 #15
but in a real world AND, OR, NOR, NAND you would have setup and hold problems

As far as C# etc are concerned, the "real world" is that AND and OR
are commutative.
So if X&Y != Y&X, then you do have 27 triplets,
No; if (with regular C# flags arithmetic) X&Y != Y&X, then your
computer needs a new CPU
and I was "right all along".
Or you just a major issue accepting that you are not perfect (none of
us are).
Get over it; we all make mistakes - only a fool refuses to accept
them. The wise also learn from them.

Marc

Sep 3 '08 #16
raylopez99 wrote:
So if X&Y != Y&X,
That would be pretty silly logic, though. <g>

--
Rudy Velthuis http://rvelthuis.de

"I love Mickey Mouse more than any woman I have ever known."
-- Walt Disney (1901-1966)
Sep 3 '08 #17
On Sep 3, 6:44*am, Marc Gravell <marc.grav...@gmail.comwrote:
>
No; if (with regular C# flags arithmetic) X&Y != Y&X, then your
computer needs a new CPU
and I was "right all along".
Or you just a major issue accepting that you are not perfect (none of
us are).
That's correct. Logically either I was "right all along"*, since I
said that the logic would have to be faulty (outside of the design
parameters of the logic), OR, as you say, I have a major issue
accepting I am not perfect. So I was correct in my statement, as you
acknowledge.

Ball is back in your court, Mr. Marc Gravell.
Get over it; we all make mistakes - only a fool refuses to accept
them. The wise also learn from them.
Then I'm a fool. Takes all kinds, or would you rather have a bunch of
brainiacs? You'd never get ahead in life if it wasn't for fools,
though I guess the world would be better off (albeit everybody would
be equal, which would be a problem).

RL

* since I knew all this during the OP, but I temporarily forgot it.
Sep 3 '08 #18
"Family Tree Mike" <Fa************@ThisOldHouse.comwrote in message
news:eD**************@TK2MSFTNGP05.phx.gbl...
>Having 28 digits can be useful at times even if you don't bother with the
fractional part.
I hadn't had that need come up yet, but it makes sense. Thanks for the
advice!
This sort of thing might come up if you ever find yourself developing a
payroll application for a Zimbabwean company :)

Sep 4 '08 #19
raylopez99 wrote:
On Sep 2, 4:07 pm, Göran Andersson <gu...@guffa.comwrote:
>Why do you think that? What potential problems could possibly come from
or:ing more than two values?


Well, what is the result of this:

X AND Y AND Z

where X,Y,Z are 0 or 1 (so you have nine combinations)

consider:

(X AND Y) AND Z

versus

(X) AND (Y AND Z)

versus

X AND Y AND Z

I think it makes a difference. Same for OR, but to a lesser degree
(if at all).
No, there is no difference. I think that you have to brush up on your
boolean algebra...

(Associativity of ?): x?(y?z) = (x?y)?z
(Associativity of ?): x?(y?z) = (x?y)?z

http://en.wikipedia.org/wiki/Boolean..._(introduction)
Same for XOR.
Of course, but that's a different operator.
That's why I don' combine more than two
flags at a time.
I see. Because you believe things that plainly are not true... That's
not a very good reason.

--
Göran Andersson
_____
http://www.guffa.com
Sep 4 '08 #20
raylopez99 wrote:
I assumed that the default would include "AllowDecimal", in other
words, that the flags would be more inclusive rather than all-
inclusive.
If you mean the default used by the overload of the method where you
don't specify a NumberStyle, it does.

If you mean the default value of the enum, the default value is always
zero. For that to allow a decimal, the flag would have to be DenyDecimal
rather than AllowDecimal. That would be awkward as all the other styles
are allowing rather than denying.

--
Göran Andersson
_____
http://www.guffa.com
Sep 4 '08 #21
Put that in your Boolean pipe and smoke it! :)

&& and || (logical) are completely different operators to & and |
(bitwise)

Seriously, every time you come back with stuff you look more
ridiculous...

Marc
Sep 4 '08 #22
He's got you guys all on his line, *hard. *:)

What you say is true; and you're right - the "respectful for short
periods of time" is getting old. I'm coming over to your "just ignore
him completely, even if he is pretending to be genuine" approach....

Marc
Sep 4 '08 #23

This discussion thread is closed

Replies have been disabled for this discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.