【问题标题】:From a float to an integer从浮点数到整数
【发布时间】:2016-11-06 23:24:27
【问题描述】:

鉴于我的教授在考试中给我们的这段代码,这意味着我们不能修改代码也不能使用其他库中的函数(stdio.h 除外):

float x;

(suppose x NOT having an integer part)
while (CONDITION){
    x = x*10
}

我必须找到条件确保x在小数点右边没有有效数字不注意浮点数的精度问题(小数点后我们有只有零)。我试过这个条件:

while ((fmod((x*10),10))){
    X = X*10
}
printf(" %f ",x);

示例:

INPUT x=0.456; --------> OUTPUT: 456.000
INPUT X=0.4567;--------> OUTPUT; 4567.000
It is important to be sure that after the decimal point we don't have any        
significant number

但我必须包含 math.h 库,但我的教授不允许我们在这种特定情况下使用它(我什至不允许使用(长时间),因为我们在课堂上从未见过它)。

那么在没有这个库的情况下正确解决问题的条件是什么?

【问题讨论】:

  • 这通常没有意义,因为浮点数不能准确地表示大多数数字,并且它的总精度将具有尽可能多的小数位数。
  • 你可以学习float type 并在内部位上做一些测试
  • 我什至不允许使用 (long),因为我们在课堂上从未见过它 这没有意义.... cast 是最简单的方法,尽管正如@2501 已经写的那样,并不准确。
  • 您的教授可能应该指定您对该测试的约束以及他/她期望的精度。如果你的教授不知道精度问题,你应该开始考虑改变学校/班级……;)
  • 请修改您的问题并给出不同输入和所需输出的清晰示例。

标签: c types integer


【解决方案1】:

如前所述:由于浮点数的准确性,这实际上是不可能的,但我认为您的教授想要得到类似的东西

while (x  - (int)x != 0 )

while (x  - (int)x >= 0.00000001 )

您可以使用 g 修饰符而不是 f 来消除零:

printf(" %g \n",x);

【讨论】:

  • 如果实际浮点值略小于预期值,这将失败。
【解决方案2】:

问题中存在模糊性(“不注意浮点数的精度问题”),但我认为下面是寻求的答案,将 x 分配给整数类型,直到 x 不再有小数部分。

此方法的成功取决于INT_MIN <= x <= INT_MAX。当float 的有效位的位数不超过int 的值位时,这是预期的。尽管这很常见,但 C 并未指定。作为替代方案,代码可以使用更宽的整数类型,如 long long,而出现范围限制问题的可能性要小得多。

鉴于*10 引入的舍入,此方法不是float 转换为文本的良好基础。

float Dipok(float x) {
  int i;
  while ((i=x) != x) {
      x = x*10;
  }
  return x;
}

#include <assert.h>
#include <stdio.h>
#include <float.h>

void Dipok_test(float x) {
  // suppose x NOT having an integer part
  assert(x > -1.0 && x < 1.0);
  float y = Dipok(x);
  printf("x:%.*f y:%.f\n", FLT_DECIMAL_DIG, x, y);
}

int main(void) {
  Dipok_test(0.456);
  Dipok_test(0.4567);
  return 0;
}

输出

x:0.456000000 y:456
x:0.456699997 y:4567

【讨论】:

  • ... 和 Dipok_test(0.001); 在我的机器上产生 x:0.001000 y:10000001
  • @undur_gongor 一个典型的float 使用binary32 格式和float x = 0.001 会将x 设置为0.001000000047497451305389404296875 的确切值。 Dipok(float x) 接收的正是这个值。鉴于 OP 指定“不注意浮点数的精度问题”,10000001 的答案是可以的。 OP 肯定会将此作为其他应用程序的基础,并将使用 while ((i=x) != x) 的循环计数来进一步处理 10010000001 或其他任何东西。
  • 虽然这在形式上是正确的,但我觉得这有点牵强。很想知道 OP 是否对这种情况下的结果感到满意。
【解决方案3】:

正如2501 已经指出的那样,这是不可能的。

浮点数不准确。根据您的平台,0.001 的浮点值实际上表示为 0.0010000001。

您希望代码计算什么:10000001 还是 1?

任何解决方案都只适用于某些值。

【讨论】:

  • 典型的 float 有 6 位以上的相对小数精度。它们的值是准确的。问题是floats 上的许多操作 会导致舍入,例如分配float x = 0.001;
【解决方案4】:

我尝试回答我的考试问题,如果我说错了请纠正我!

不可能找到确保小数点后没有有效数字的适当条件。例如:我们想知道 0.4*20 的结果是 8.000 但是由于不精确的问题输出会有所不同:

f=0.4;
for(i=1;i<20;i++)
   f=f+0.4;
printf("The number f=0.4*20 is ");
if(f!=8.0) {printf(" not ");}
printf(" %f ",8.0);
printf("The real answer is f=0.4*20= %f",f);

我们的输出将是:

The number f=0.4*20 is not 8.000000 

The real answer is f=0.4*20= 8.000001

【讨论】:

  • 我不应该使用除 stdio.h 之外的其他库中的函数,我只使用 printf 只是为了表明浮点数不精确。
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 2016-10-01
  • 2018-06-16
  • 2011-01-04
  • 2012-03-28
相关资源
最近更新 更多