我有两段小小的代码。在我看来,他们应该得到相同的字符串,但他们不这样做:为什么具有相同值的两位小数格式不同
(1.23M * 100M).ToString()
结果:
123,00
和
(123M).ToString()
结果:
123
我的问题很简单:can som ebody向我解释为什么这种(奇怪的?)行为发生?
我有两段小小的代码。在我看来,他们应该得到相同的字符串,但他们不这样做:为什么具有相同值的两位小数格式不同
(1.23M * 100M).ToString()
结果:
123,00
和
(123M).ToString()
结果:
123
我的问题很简单:can som ebody向我解释为什么这种(奇怪的?)行为发生?
它们是两个不同的值,按位。与double
不同,decimal
不会自动标准化 - 它看起来像保留了在某一点上有两位小数位的信息。你可以看到完全一样的差,而没有乘法:
Console.WriteLine(123m)
Console.WriteLine(123.00m);
的文档有些含糊(从我所看到的)究竟是如何进行操作的上decimal
值的结果,在多少位小数的条款被保留。 (我也不会感到惊讶地得知,它的标准的地方...)
的decimal
类型是由10倍。从文档缩放整数代表了decimal
:
缩放因子还保留了一个十进制数中的任何尾随零。在算术或比较操作中,尾部零不会影响十进制数的值。但是,如果应用了适当的格式字符串,则ToString方法可能会显示尾随零。
使用GetBits
可以看到123.00M
被表示为十分之一万二千三百而123M
是10分之123。
编辑
我参加了一个简单的程序,演示功能的问题:
class Program
{
static void Main(string[] args)
{
Console.WriteLine((1.23M * 100M).ToString());
Console.WriteLine((123M).ToString());
}
}
我看着产生IL:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 51 (0x33)
.maxstack 6
.locals init ([0] valuetype [mscorlib]System.Decimal CS$0$0000)
IL_0000: nop
IL_0001: ldc.i4 0x300c
IL_0006: ldc.i4.0
IL_0007: ldc.i4.0
IL_0008: ldc.i4.0
IL_0009: ldc.i4.2
IL_000a: newobj instance void [mscorlib]System.Decimal::.ctor(int32,
int32,
int32,
bool,
uint8)
IL_000f: stloc.0
IL_0010: ldloca.s CS$0$0000
IL_0012: call instance string [mscorlib]System.Decimal::ToString()
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: nop
IL_001d: ldc.i4.s 123
IL_001f: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0024: stloc.0
IL_0025: ldloca.s CS$0$0000
IL_0027: call instance string [mscorlib]System.Decimal::ToString()
IL_002c: call void [mscorlib]System.Console::WriteLine(string)
IL_0031: nop
IL_0032: ret
} // end of method Program::Main
我们可以看到,编译器实际上优化除去乘法并将调用插入到构造第一种情况的单个十进制实例中。这两个实例使用不同的表示。他们基本上是我上面所描述的。
有关于此的文档,但不幸的是,实际行为并不100%符合规范。 –