【问题标题】:How to count the decimal places of an double variable in c++?如何计算c ++中双变量的小数位?
【发布时间】:2014-03-27 22:02:27
【问题描述】:

对于我大学的一门课程,我需要编写一个将数字转换为 自然语言,例如如果用户输入“2.55”,程序输出“二点五五”。 我快要完成它了,我唯一不能得到的是点后的数字。 我不允许使用字符串。以下是我尝试获取小数位数的方法:

i=0;
while((wert - (long int)wert) != 0){
    wert /= 10;
    i++;
}

但它给了我示例数字“2.55”的小数点后 356 位的值。有没有不使用字符串计算小数位的方法?

最好的问候

【问题讨论】:

  • 浮点不能那样工作......很难预测像“2.55”这样的数字将如何存储为双精度 - 你可能会得到像“2.549999......”这样的数字。选择一个固定的精度并坚持下去。
  • 不要与零精确比较,而是尝试检查零和数字之间的差异是否非常小。
  • 预期输入的数字范围是多少?它是 64 位系统的完整浮点范围吗?是否允许将输入解析为两个独立的整数?根据答案,您可能能够以不同的方式解析输入。
  • 用他的话来说,该程序应该能够向您显示任何在 double 范围内的实数应该可以表示,例如“2.1”应该给出“两点一”,“2.10”应该给出“牵引点一零”。
  • 您以什么格式接收您的输入?我假设您正在接收字符串,然后将它们转换为双精度数?为了正确解析“2.1”和“2.10”,您将不得不使用原始字符串或其他一些信息(如最大 sig-figs 数)......否则我理解它是不可能的。跨度>

标签: c++ floating-point double decimal


【解决方案1】:

由于浮点精度,您将无法使用double 执行此操作。例如,double 设置为 0.2 的小数位数将比 1 多得多,因为 0.2 无法精确表示。 (为什么不在调试器中检查double 的实际值?)2.55 也不能精确表示。

您在这里做的最简单的事情可能是使用一个字符串来表示您的号码并以此为基础您的解析器。

【讨论】:

  • 那是我的问题,我已经使用字符串完成了程序,但我的教授坚持只使用双精度类型。
  • 这使问题变得人为地困难。你确定教授坚持吗?
  • 是的,他坚持只使用双精度和整数数据类型,但据他说我只需要双精度。
  • @Cracksoldier 总而言之,分配人为地限制不使用任何字符或字符串解析技术。
【解决方案2】:

如果用户输入数字,它将以字符串的形式输入,或者我们应该说是字节数组,因此根本不需要将浮点数带入其中。只需找到数据中的小数位,然后开始计算数字。

NB 你标题中的问题毫无意义。浮点型变量没有小数位,有二进制位,小数位和二进制位不可通约。如果您的教授希望您使用浮点数,他需要 re-education 本人。

【讨论】:

  • 据我了解,要求是处理double。当然,您可以谈论小数位 - 这是双精度的十进制表示中的位置。 IIRC,实现(过去)存在浮点数不以 IEEE/二进制形式存储的地方。
  • @Axel 没错,您可以讨论将双精度转换为小数的结果中的小数位。不在双重本身。这是没有意义的。他们不在里面。
  • 因为每个双精度数都代表一个唯一的数字,个小数位,我认为这意味着什么很清楚。同样,根据您的定义,在某些系统(大型机就是一个例子)中,C 中的浮点值 not 具有二进制位置。至于任务本身:我认为它可以作为一项作业,因为这真的可以让人大开眼界,而且我很确定教授知道你链接的文章。至少我希望如此。
【解决方案3】:

最接近 2.55 的 IEEE 64 位二进制数是 2.54999999999999982236431605997495353221893310546875,小数点后只有 50 位。

重复的划分没有意义。忽略舍入误差,wert 的值将是 2.55、0.255、0.0255、0.00255 等。它们都不等于任何 long。当wert 下溢为零时,循环终止。

相反,您应该乘以 10。但是,如果您保留前导数字,您可能会得到一个太大而无法在获得相等之前存储为 long 的数字。相反,我建议在每一步减去整数部分,并在结果为零时停止。

这仍然会导致小数点后 50 位的答案,但如果你的教授坚持双倍,也许这就是想要的。

【讨论】:

  • 这是一个很好的答案。它触及了问题的根本荒谬或模糊性。 2.55 可以合理地打印 3 到 50 位数字。从浮点数的角度来看,每个 32 位浮点数都可以通过符号、指数和 9 位十进制尾数来唯一标识。然而,在大多数情况下,这并不能为您提供该浮动的精确值——只是附近的一个。在最坏的情况下,浮点数可能需要 112 位才能精确打印,而双精度数则更糟。 randomascii.wordpress.com/2012/03/08/…
【解决方案4】:
char* fractpart(double f)
{
char chrstr[5];
char charary={'1','2','3',....,'0'};
int intary={1,2,3,...,0};
int count=0,x,y;
f=f-(int)f;
        while(f<=1)
        {
         f=f*10;
           for(y=0;y<10;y++)
           {
               if((int)f==intary[y])
               { 
               chrstr[count]=charary[y];
               break;
               }
           }
   f=f-(int)f;
      if(f<=0.01 || count==4)
      break;
      if(f<0)
      f=-f;
      count++;
}
     return(chrstr);
}

【讨论】:

  • 欢迎来到 SO。如果您包含对代码如何工作以及它如何回答问题中描述的问题的解释,您的答案将更加有用。见stackoverflow.com/help/how-to-answer
  • 请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
【解决方案5】:

您必须知道在该点之后必须支持的最大位数。假设n 位数最大。将数字的小数部分乘以10^n,然后右移所得数字,直到最后一位数字与0 不同,以删除尾随零。然后将数字一个一个打印出来:

void printDigitsAfterPoint(double x) {
    int k = Math.round((x-(int) x)*Math.pow10(n));
    // remove trailing zeroes
    while (k!=0 && k%10==0) {
        k/=10;
    }
    // output digits
    while (k!=0) {
        output(k%10); // you already should have a method like this...
        k/=10;
    }
}

确保添加处理x 负值的代码。我相信你的教授会尝试的......

编辑:忘记更改声明。固定。

【讨论】:

  • 我在程序顶部的“cin”之后直接添加了处理负值的代码
  • 嗯,还有一个问题:您需要的是数字,而不是数字的数量,对吧?我误解了你的问题。将再次更新。
  • 这很可能会非常不可靠,因为:10.0 times 0.1 is hardly ever 1.0 ~Brian Kernighan
  • 不,10 times 0.1 始终是 1.0。问题是,没有0.1... ;-)
  • 您可以随心所欲地使用它们。在第二个循环中是k%10
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多