更新
好的,經過一番調查,並且在很大程度上感謝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;
}
}
我還沒有完全測試過它。這裏有幾個樣品輸入/輸出,但:
Value Precision 0 1 digit(s). 0.000 4 digit(s). 1.23 3 digit(s). 12.324 5 digit(s). 1.2300 5 digit(s). -5 1 digit(s). -5.01 3 digit(s). -0.012 4 digit(s). -0.100 4 digit(s). 0.0 2 digit(s). 10443.31 7 digit(s). -130.340 6 digit(s). -80.8000 6 digit(s).
使用此代碼,我想我會做這樣的事情完成我的目標:
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")
爲a
and decimal.Parse("1.23000")
for b
(whi ch表示該問題適用於程序收到用戶輸入的情況)。
所以很清楚,decimal
值是以某種方式「知道」我將其稱爲精度。但是,除ToString
本身外,我沒有看到decimal
類型的成員提供任何訪問此方法的方法。
假設我想要乘以兩個decimal
值並將結果修剪爲精度較低的參數。換句話說:
decimal a = 123.4M;
decimal b = 5.6789M;
decimal x = a/b;
Console.WriteLine(x);
以上輸出:
21.729560302171195125816619416
什麼我問的是:我怎麼能寫會返回21.73
替代的方法(因爲123.4M
有四個顯著數字)?
要清楚:我意識到我可以在兩個參數上調用ToString
,計算每個字符串中的有效數字,並使用此數字來計算結果。如果可能,我正在尋找不同的方式。
(我也意識到,在你處理顯著數字大多數情況下,你可能並不需要使用的decimal
類型。但是,我這麼問是因爲,正如我在開始提到的, decimal
類型出現包含有關精度的信息,而double
並不如我所知。)
我不知道我想知道這個,直到你問它+1! – msarchet 2010-09-10 14:35:06
您的功能對某些輸入無法正常工作。例如,-0.012只有2位有效數字 - 不是4. – 2011-03-29 18:11:06
@JamesJones顯然他指的是有效數字的不同概念,而不是數學課程中學習的數字。也許「使用數字」這個名字會更有意義。 – ErikE 2015-08-21 22:43:29