why can't you assign a number with a decimal point to decimal type directly without using type suffix?
Asked Answered
C

6

71

Why can't you assign a number with a decimal point to the decimal type directly without using type suffix? isn't this kind of number considered a number of type decimal?

decimal bankBalance = 3433.20; // ERROR!
Cystoid answered 27/1, 2009 at 20:51 Comment(3)
Did we all miss the last part of the question or was that just added?Ostrich
The reason, as I and others said, is that there is no implicit type conversion done. If you enter 3433.20, that's a float by default. C# won't convert a float to a decimal. I don't know why they made this decision, but MSDN shows that this is the case.Ecology
My answer below has the link msdn.microsoft.com/en-us/library/364x0z75(VS.80).aspx to MSDN where they explain this.Ecology
O
116

Edit: I may have missed the last part of the question, so the overview below is hardly useful.

Anyway, the reason you can't do what you're trying to do is because there is no implicit conversion between floating point types and decimal. You can however assign it from an integer, as there is an implicit conversion from int to decimal.


You can, but you have to use this syntax (or do an explicit cast to decimal).

decimal bankBalance = 3433.20m;

and for floats it is

float bankBalance = 3433.20f;

default is double

double bankBalance = 3444.20;
Ostrich answered 27/1, 2009 at 20:57 Comment(3)
Correct, but the explicit cast doesn't make it any easier to read imo, but you're right.Ostrich
what does "m" stand for?Loquitur
@ThePoet d suffix was already taken by double, so they decided to use m for deciMal. See: https://mcmap.net/q/80241/-what-does-the-m-stand-for-in-c-decimal-literal-notationTransect
I
22

Actually, hidden spec feature: you can ;-p

decimal bankBalance = (decimal)3433.20;

This is genuinely parsed by the compiler as a decimal (not a float and a cast). See the IL to prove it. Note that the precision gets truncated, though (this has 1 decimal digit, not the 2 you get from the M version).

IL generated:

L_0001: ldc.i4 0x861c
L_0006: ldc.i4.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ldc.i4.1 
L_000a: newobj instance void [mscorlib]System.Decimal::.ctor(int32, int32, int32, bool, uint8)
L_000f: stloc.0 

Compared to:

decimal bankBalance = 3433.20M;

Which generates:

L_0001: ldc.i4 0x53d18
L_0006: ldc.i4.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ldc.i4.2 
L_000a: newobj instance void [mscorlib]System.Decimal::.ctor(int32, int32, int32, bool, uint8)
L_000f: stloc.0 

The only difference is the decimal digits (1 vs 2, and a factor of 10, accordingly)

Impeachment answered 27/1, 2009 at 23:30 Comment(4)
Is really a literal decimal? Or is it just casting a double like it looks like?Weatherbound
I'm not entirely sure (I haven't checked it), but I'm guessing this will generate a runtime cast from a double to a decimal.Cupel
It is really a decimal. See the IL.Impeachment
I did just check the IL, and you're right. Although its weird that there's just one decimal digit... I did test it with the Mono C# compiler, so maybe it's part of the C# language spec.Cupel
H
7

This

decimal bankBalance = 3433.20M;

will work. The reason is that float and decimal are very different types. float will give you an extremely close approximation of the number you enter, but decimal will give you the exact number. 99% of the time you wont notice the difference, and should just use float.

Homosporous answered 27/1, 2009 at 20:58 Comment(1)
"Bank balances" and other monetary values being in that 1% of cases.Slayton
L
5

Your answer consists of two important points:

  1. All numerical literals with a decimal point are inferred to be of type double by the C# compiler, consequently, 3433.20 is a double by default.

  2. double numbers do not implicitly convert to decimal because although decimal is more precise than double it covers a shorter range so overflow is possible during a cast from double to decimal.

double's range: ±(~10^−324 to 10^308) with 15 or 16 significant figures.

decimal's range: ±(~10^-28 to 10^28) with 28 or 29 significant figures.

Leede answered 21/11, 2011 at 8:57 Comment(2)
downvoted, although more information is always helpful, you didn't answer his questionLoquitur
@ThePoet, the answer to the question is precisely because the type is not considered a decimal, but a double, which has a wider range than decimal and can't be assigned to it implicitly because of possible data loss (it's actually quite unfortunate that the higher answers don't mention this to inform people why you should explicitly include that suffix). Those point are included in the answer so I believe this more than answers the question.Leede
E
3

See the MSDN page on decimal which explains that there is no implicit conversion between normal float types and decimal.

Try

decimal bankBalance = 3433.20m;

Ecology answered 27/1, 2009 at 20:58 Comment(0)
H
0

I really like Convert class in many cases. Its very reliable.

decimal bankBalance = Convert.ToDecimal(3433.20);

Houphouetboigny answered 19/10, 2021 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.