C# 查找双精度小数点后的位数

C# 查找双精度小数点后的位数,c#,C#,我有一个双重价值: double a = 4.5565; 计算小数点后位数(本例中为4)的最简单方法是什么 我知道我可以转换成字符串,进行拆分并计算长度。但是有更简单的方法吗?没有简单的方法,特别是因为从数学上讲,数字的数量可能远远超过显示的数字。例如,4.5565实际上存储为4.55649999999772626324556767940521240234375(感谢您的计算)。你不大可能找到解决这个问题的有效方法 编辑 你可以想出一些这样的算法:如果在计算十进制表示法时,你连续找到一定数量的

我有一个双重价值:

double a = 4.5565;
计算小数点后位数(本例中为4)的最简单方法是什么


我知道我可以转换成字符串,进行拆分并计算长度。但是有更简单的方法吗?

没有简单的方法,特别是因为从数学上讲,数字的数量可能远远超过显示的数字。例如,4.5565实际上存储为
4.55649999999772626324556767940521240234375
(感谢您的计算)。你不大可能找到解决这个问题的有效方法

编辑


你可以想出一些这样的算法:如果在计算十进制表示法时,你连续找到一定数量的9(或零),你可以向上(或向下)取整到9(或零)序列开始之前的最后一位。我怀疑你在这条路上会遇到比你预期的更多的麻烦。

我认为字符串解决方案是最好的:
((a-(int)a)+>)。length-2

var precision = 0;
var x = 1.345678901m;

while (x*(decimal)Math.Pow(10,precision) != 
         Math.Round(x*(decimal)Math.Pow(10,precision))) 
   precision++;
精度
将等于十进制值的有效位数(将x设置为1.2345600将导致精度为5,即使最初在文本中指定了8位)。此操作的执行时间与小数位数成比例。它只计算小数位数;通过取Math.Log10(x)的整数部分,可以计算小数点左边的位数。它最适用于小数,因为小数具有更好的值精度,因此舍入误差更小。

编写一个函数

int CountDigitsAfterDecimal(double value)
        {
            bool start = false;
            int count = 0;
            foreach (var s in value.ToString())
            {
                if (s == '.')
                {
                    start = true;
                }
                else if (start)
                {
                    count++;
                }
            }

            return count;
        }

如果需要,我可能会使用这个代码

myDoubleNumber.ToString("R").Split('.')[1].Length
“R”
这里是


当然,我们首先需要检查索引边界。

我认为这可能是一个解决方案:

 private static int getDecimalCount(double val)
 {
     int i=0;
     while (Math.Round(val, i) != val)
         i++;
     return i;
 }

double val9 = 4.5565d; int count9 = getDecimalCount(val9);//result: 4

抱歉重复->

基于詹姆斯的回答,更清楚:

int num = dValue.ToString().Length - (((int)dValue).ToString().Length + 1);
num是小数点后的精确位数。 不包括这样的0(25.520000
在这种情况下,您将得到num=2,另一种解决方案是使用一些字符串函数:

private int GetSignificantDecimalPlaces(decimal number, bool trimTrailingZeros = true)
{
  string stemp = Convert.ToString(number);

  if (trimTrailingZeros)
    stemp = stemp.TrimEnd('0');

  return stemp.Length - 1 - stemp.IndexOf(
     Application.CurrentCulture.NumberFormat.NumberDecimalSeparator);
}

记住使用System.Windows.Forms访问Application.CurrentCulture

您所说的“更简单”是什么意思?从写/读的角度来看,我怀疑还有什么比这更容易的方法,但在CPU操作方面,可能会有一些更容易的方法,例如,这实际上是不可能的。
a
的值可能不是精确的4.5565。如果你不明白为什么,我建议你读一读:这取决于,你想计算什么样的小数?会出现在C#的ToString中的那些?代表真实准确性的那些?或者所有以10为基数的整数值转换中出现的数值?请注意,对于
十进制
,这是可能的。您只需不在字符串中计算
0.
。与blitzkriegz的解决方案没有太大区别添加“”是调用
ToString()
@JonSkeet的真正可怕的替代方法为什么?如果一个对象为null,toString可能会失败,那么它总是可以工作的(当然,在这个例子中,a是基元的情况下不是这样)。就个人而言,我不希望看到这一点,因为它混淆了代码的意图。当您看到一个ToString()调用时,您就知道编码人员试图做什么,并且通常不难找到字符串转换的实现。字符串连接剥夺了意图,需要更多的知识和时间来弄清楚会发生什么。这种方式太“聪明”(聪明的代码对可维护性来说是一件坏事)。这主意不错,但你也应该检查“a”是否是否定的。@phoog我大体上同意你所说的,但你对我的答案怎么看?@DorCohen我现在没有时间深入研究你的答案。今晚晚些时候或明天早上我会试着看一看。之前的评论是作为32位浮点,应该是:4。556499999999999772626324556767940521240234375@phoog我在哪里可以了解它为什么存储为4。556499999999999772626324556767940521240234375@blitzkriegz其他人在对您的问题的评论中建议的链接是对IEEE浮点系统的良好讨论。我认为没有必要再增加一些。简单的回答是二进制表示法在基数2中,有许多值在基数10中是有限小数,但在基数2中是无限的;这些必须被截断(类似于0.3333333是1/3的截断十进制近似值)。harold计算的数字是值4.5565的不精确二进制近似值的精确十进制表示。@batsheva正如我所说的,首先检查数组索引边界。这对于以标准形式表示的数字(例如5.821E+12)不正确,因为小数点总是排在第二位。在给出的示例中,结果实际上应该是0,因为5.821E+12是一个非常大的整数。另外需要考虑的是,某些区域性不使用“.”作为小数分隔符,因此应为“ToString()”指定“CultureInfo.InvariantCulture”。