4

2 つの小さなコードがあります。私の意見では、それらは同じ文字列になるはずですが、そうではありません:

(1.23M * 100M).ToString()

結果:

123,00

(123M).ToString()   

結果:

123

私の非常に単純な質問は、誰かがなぜこの (奇妙な?) 動作が起こるのか説明してもらえますか?

4

2 に答える 2

4

型は、decimal10 倍にスケーリングされた整数で表されますdecimal

スケーリング係数は、10 進数の末尾のゼロも保持します。末尾のゼロは、算術演算または比較演算の 10 進数の値には影響しません。ただし、適切な書式文字列が適用されている場合、ToString メソッドによって末尾のゼロが明らかになることがあります。

を使用すると、 12300 / 10 2として表され、123 / 10 0GetBitsとして表されることがわかります。123.00M123M

編集

この問題を説明する簡単なプログラムを作成しました。

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

コンパイラが実際に乗算を最適化し、最初のケースで単一の 10 進インスタンスの構成への呼び出しを挿入したことがわかります。2 つのインスタンスは異なる表現を使用しています。それらは基本的に私が上で説明したものです。

于 2013-07-07T20:41:51.130 に答える
3

これらは、ビット単位の 2 つの異なる値です。とは異なりdoubledecimalは自動的に正規化されません。ある時点で小数点以下 2 桁だったという情報が保持されているようです。乗算なしでまったく同じ違いを見ることができます。

Console.WriteLine(123m)
Console.WriteLine(123.00m);

decimalドキュメントは、保持される小数点以下の桁数に関して、値に対する操作の結果がどのように実行されるかについて、(私が見る限り) やや不明確です。(どこかで標準化されていることを知っても驚かないでしょう...)

于 2013-07-07T20:37:30.597 に答える