アップデート
OK、いくつかの調査の後、Jon と Hans から提供された有益な回答のおかげで、これが私がまとめることができたものです。これまでのところ、うまく機能しているように思えます。もちろん、その完全な正しさに命を賭けるつもりはありません。
public static int GetSignificantDigitCount(this decimal value)
{
/* So, the decimal type is basically represented as a fraction of two
* integers: a numerator that can be anything, and a denominator that is
* some power of 10.
*
* For example, the following numbers are represented by
* the corresponding fractions:
*
* VALUE NUMERATOR DENOMINATOR
* 1 1 1
* 1.0 10 10
* 1.012 1012 1000
* 0.04 4 100
* 12.01 1201 100
*
* So basically, if the magnitude is greater than or equal to one,
* the number of digits is the number of digits in the numerator.
* If it's less than one, the number of digits is the number of digits
* in the denominator.
*/
int[] bits = decimal.GetBits(value);
if (value >= 1M || value <= -1M)
{
int highPart = bits[2];
int middlePart = bits[1];
int lowPart = bits[0];
decimal num = new decimal(lowPart, middlePart, highPart, false, 0);
int exponent = (int)Math.Ceiling(Math.Log10((double)num));
return exponent;
}
else
{
int scalePart = bits[3];
// Accoring to MSDN, the exponent is represented by
// bits 16-23 (the 2nd word):
// http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx
int exponent = (scalePart & 0x00FF0000) >> 16;
return exponent + 1;
}
}
私はそれをすべて徹底的にテストしていません。ただし、入力/出力の例をいくつか示します。
値の精度 0 1 桁。 0.000 4 桁。 1.23 3桁。 12.324 5桁。 1.2300 5桁。 -5 1 桁。 -5.01 3桁。 -0.012 4 桁。 -0.100 4 桁。 0.0 2桁。 10443.31 7桁。 -130.340 6 桁。 -80.8000 6 桁。
このコードを使用すると、次のようなことを行うことで目標を達成できると思います。
public static decimal DivideUsingLesserPrecision(decimal x, decimal y)
{
int xDigitCount = x.GetSignificantDigitCount();
int yDigitCount = y.GetSignificantDigitCount();
int lesserPrecision = System.Math.Min(xDigitCount, yDigitCount);
return System.Math.Round(x / y, lesserPrecision);
}
しかし、私はこれを完全にやり遂げたわけではありません。考えを共有したい人なら誰でも:それは大歓迎です!
元の質問
次のコードを書いたとします。
decimal a = 1.23M;
decimal b = 1.23000M;
Console.WriteLine(a);
Console.WriteLine(b);
上記は次のように出力されます。
1.23 1.23000
decimal.Parse("1.23")
fora
とdecimal.Parse("1.23000")
forを使用すると、これも機能することがわかりましたb
(つまり、この質問は、プログラムがユーザー入力を受け取る場合に適用されます)。
したがって、明らかにdecimal
値は、私がその精度と呼ぶものを何らかの形で「認識」しています。decimal
ただし、それ自体を除いて、これにアクセスする方法を提供するタイプのメンバーはありませんToString
。
decimal
2 つの値を乗算し、結果を精度の低い引数の精度にトリムしたいとします。言い換えると:
decimal a = 123.4M;
decimal b = 5.6789M;
decimal x = a / b;
Console.WriteLine(x);
上記の出力:
21.729560302171195125816619416
私が求めているのは、21.73
代わりに返されるメソッドをどのように書くことができるかということです ( 123.4M
4 つの有効数字があるため)。
明確にするために、両方の引数を呼び出しToString
、各文字列の有効数字を数え、この数値を使用して計算結果を丸めることができることを理解しています。可能であれば、別の方法を探しています。
(また、有効数字を扱っているほとんどのシナリオでは、おそらく型を使用する必要がないことも認識しています。しかし、最初に述べたように、型には次の情報が含まれているように見えるdecimal
ので、私が尋ねているのです。私が知る限り、正確ではありません。)decimal
double