69

C# のこれらの行

decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;

Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);

次の出力が生成されます。

2
2.0
2.00000000
2.000000000000000000000000000

したがって、リテラルから 10 進変数を作成すると、精度を制御できることがわかります。

  • リテラルを使用せずに 10 進変数の精度を調整できますか?
  • a から b を作成するにはどうすればよいですか? c から b を作成するにはどうすればよいですか?
4

7 に答える 7

57

このような後続ゼロの保持は、ECMACLI仕様へのより厳密な準拠のために.NET1.1で導入されました。

これに関する情報はMSDNにあります(例:ここ) 。

次のように精度を調整できます。

  • 精度を下げるためのMath.Round(またはCeiling、Floorなど)(cからb)

  • 精度を上げるには、1.000 ...(必要な小数点以下の桁数を使用)を掛けます。たとえば、1.0Mを掛けて、aからbを取得します。

于 2009-07-15T20:37:02.957 に答える
19

まったく同じデータの異なる表現が表示されているだけです。a の精度は、decimal(妥当な範囲内で) 必要なだけ大きくなるようにスケーリングされます。

からSystem.Decimal:

10 進数は、符号、値の各桁の範囲が 0 ~ 9 の数値、および整数部分と小数部分を区切る浮動小数点の位置を示すスケーリング係数で構成される浮動小数点値です。数値の。

Decimal 値のバイナリ表現は、1 ビットの符号、96 ビットの整数、および 96 ビットの整数を除算し、小数部分を指定するために使用されるスケーリング係数で構成されます。倍率は、暗黙的に 10 を 0 から 28 の範囲の指数で累乗したものです。したがって、10 進値のバイナリ表現は、((-2 96から 2 96 ) / 10 (0 から 28) )の形式になります。ここで、-2 96 -1 は MinValue に等しく、2 96 -1 は MaxValue に等しくなります。

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

于 2009-07-15T17:26:55.850 に答える
8

Math.Round(decimal d, int decimals) はどう ですか?

于 2009-07-15T17:50:05.257 に答える
7

ファンシーな 1 を掛けたり割ったりすることで、スケールを「改ざん」できることがわかりました。

decimal a = 2m;
decimal c = 2.00000000m;
decimal PreciseOne = 1.000000000000000000000000000000m;
  //add maximum trailing zeros to a
decimal x = a * PreciseOne;
  //remove all trailing zeros from c
decimal y = c / PreciseOne;

既知のサイズで倍率を変更するのに十分な精度の 1 を作成できます。

decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;

for (int i = 0; i < scaleFactorSize; i++)
{
  scaleFactor *= scaleFactorBase;
}

decimal z = a * scaleFactor;
于 2009-07-15T18:38:05.457 に答える
6

decimalSQL Server とdecimal.NETを混同しがちです。それらはかなり異なります。

SQL Serverdecimalは、列または変数の定義時に精度と位取りが固定される固定小数点数です。

.NETはandのdecimalような浮動小数点数です(違いは、10 進数を正確に保持し、 2 進数を正確に保持することです)。.NET の精度を制御しようとしても無意味です。パディング ゼロの有無に関係なく、すべての計算で同じ結果が得られるからです。floatdoubledecimalfloatdoubledecimal

于 2009-08-25T21:09:48.807 に答える
2

これにより、小数点からすべての後続ゼロが削除され、を使用できますToString()

public static class DecimalExtensions
{
    public static Decimal Normalize(this Decimal value)
    {
        return value / 1.000000000000000000000000000000000m;
    }
}

または、末尾のゼロの正確な数、たとえば5が必要な場合は、最初にNormalize()を実行してから、1.00000mを乗算します。

于 2013-01-09T18:18:53.407 に答える
1

問題は、小数を必要な精度で表示するだけでなく、小数に格納された精度が本当に必要かということです。ほとんどのアプリケーションは、必要な精度を内部的に認識しており、その精度レベルで表示します。たとえば、ユーザーがアカウント パッケージに 100 の請求書を入力しても、val.ToString("n2") などを使用して 100.00 として出力されます。

a から b を作成するにはどうすればよいですか? c から b を作成するにはどうすればよいですか?

c to bが可能です。

Console.WriteLine(Math.Round(2.00000000m, 1)) 

2.0 を生成します

精度を導入するという概念は数学とは少し異質であるため、a から b は注意が必要です。

恐ろしいハッキングは往復になる可能性があると思います。

decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);

2.0 を生成します

于 2009-07-15T18:03:36.947 に答える