【问题标题】:Determining if a float has a fractional part?确定浮点数是否有小数部分?
【发布时间】:2011-12-18 02:10:01
【问题描述】:

问题是:Totals 游戏可以由任意数量的人玩。它从总共 100 开始,然后每个玩家依次在 -20 到 20 之间进行整数位移。获胜者是调整使总数等于 5 的玩家。仅使用给定的三个变量: 全部的 调整 柜台 这是我到目前为止所拥有的:

#include <stdio.h>
int main (void)
{
    int counter=0;
    float adj;
    int ttl=100;

    printf("You all know the rules now lets begin!!!\n\n\nWe start with 100. What is\n");

    while (ttl!=5)
    {
        printf("YOUR ADJUSTMENT?");
        scanf("%f",&adj);
        counter++;
        if (adj<=20 && adj>=-20)
        {
        ttl=ttl+adj;
        printf("The total is %d\n",ttl);
        }
        else
        {
        printf ("I'm sorry. Do you not know the rules?\n");
        }
    }
    printf("The game is won in %d steps!",counter);

}

我需要什么: 当输入十进制数时,它会转到 else。如何确定浮点数是否有小数部分。

【问题讨论】:

  • 在二进制级别,没有浮点数有小数。 en.wikipedia.org/wiki/IEEE_754-2008
  • 我们在这里谈论浮动。它总是“有小数”。请改用double。 (仅供参考@Chris,我的意思是一样的)
  • @TomvanderWoerdt:double 有什么不同?
  • @OliCharlesworth 每个人都一直告诉我,双精度和浮点数的区别在于浮点数有精度误差,而双精度数允许您存储更少的数据。如果我错了,请纠正我。
  • 只是出于好奇,为什么那个程序中有float?只涉及整数。

标签: c floating-point floating-point-conversion


【解决方案1】:

您可以将float 转换为int,然后将其与您的原始变量进行比较。如果它们相同,则没有小数部分。

通过使用这种方法,不需要临时变量或函数调用。

  float adj;

  ....     

  if (adj == (int)adj)
    printf ("no fractional!\n");
  else
    printf ("fractional!\n");
  

说明

由于int 无法处理分数,您的float 的值将被截断为int(例如(float)14.3 将被截断为(int)14)。

当比较 1414.3 时,很明显它们不是同一个值,因此是“分数!”将被打印出来。

【讨论】:

  • 您不需要显式转换回float,它会自动转换。您的解决方案没有错,我只是将其写为f == (int)f,我觉得它更易于阅读和理解。
  • @Kevin 我在你写评论的同时编辑了,然后我添加了一些关于此事的更多信息,谢谢。
  • 我不相信使用这种技术的所有答案都是可靠的。如果adj 实际上是中间计算的结果,它可能保存在扩展精度寄存器中。所以比较可能会返回false,即使稍后检查adj,它实际上是一个整数值。
  • 你完全确定这行得通吗? 14 作为浮点数实际上将由大约 13.9999239894 表示。所以大多数时候比较会失败。
【解决方案2】:
#include <stdio.h>
#include <math.h>

int main ()
{
  float param, fractpart, intpart;

  param = 3.14159265;
  fractpart = modff (param , &intpart);
  return 0;
}

http://www.cplusplus.com/reference/clibrary/cmath/modf/

modff 找到小数部分,所以我想测试它是否等于 0null 会回答你的问题。

【讨论】:

    【解决方案3】:

    如果您想知道实数x 是否没有小数部分,请尝试x==floor(x)

    【讨论】:

    • @sarnold,在这种情况下不是,不是。可以表示为 floatdouble 的整数被精确表示,floor 与那些不能表示的整数没有错误。
    • 感谢您提供更详细的回答。 :)
    • 我不相信使用这种技术的所有答案都是可靠的。如果adj 实际上是中间计算的结果,它可能保存在扩展精度寄存器中。所以比较可能会返回false,即使稍后检查adj,它实际上是一个整数值。
    【解决方案4】:

    我只是在学习 C,如果我错了,请告诉我。

    但如果不是使用

    scanf("%f",&adj);
    

    如果你使用:

    scanf("%d%d", &adj, &IsUndef);
    

    因此,如果用户键入的不是整个整数,&IsUndef 将不等于 NULL,并且必须有一个小数部分将用户发送到 else。

    也许吧。

    【讨论】:

      【解决方案5】:

      使用scanf() 是有问题的。如果用户在输入的第一行输入-5 +10 -15 -15,然后按回车,您将使用scanf() 依次处理这4 个数字。这可能不是您想要的。此外,当然,如果用户键入+3 or more,则在读取空间后第一次转换停止,并且所有后续转换在oor 上都失败,并且代码进入循环。您必须检查来自scanf() 的返回值,以了解它是否能够转换任何内容。

      预读问题非常严重,我会选择使用fgets() 读取一行数据,然后使用sscanf() 的准标准替代方案(额外的s 很重要)解析一个数字。

      要确定浮点数是否有小数部分和整数部分,您可以使用modf() or modff() 函数 - 后者因为您的adjfloat

      #include <math.h>
      
      double modf(double x, double *iptr);
      float modff(float value, float *iptr);
      

      返回值为x的有符号小数部分; iptr 中的值是整数部分。请注意,modff() 可能在不支持 C99 的编译器(运行时库)中不可用。在这种情况下,您可能必须使用doublemodf()。但是,限制用户输入具有%d 格式的整数和adj 的整数类型可能同样简单;这就是我从一开始就要做的。

      另一个细节点:您真的要在总尝试次数中计算无效数字吗?

      #include <stdio.h>
      #include <math.h>
      
      int main(void)
      {
          int counter=0;
          int ttl=100;
      
          printf("You all know the rules now lets begin!!!\n"
                 "\n\nWe start with 100. What is\n");
      
          while (ttl != 5)
          {
              char  buffer[4096];
              float a_int;
              float adj;
      
              printf("YOUR ADJUSTMENT?");
              if (fgets(buffer, sizeof(buffer), stdin) == 0)
                  break;
              if (sscanf("%f", &adj) != 1)
                  break;
              if (adj<=20 && adj>=-20 && modff(adj, &a_int) == 0.0)
              {
                  counter++;  // Not counting invalid numbers
                  ttl += adj;
                  printf("The total is %d\n", ttl);
              }
              else
              {
                  printf ("I'm sorry. Do you not know the rules?\n");
              }
          }
      
          if (ttl == 5)
              printf("The game is won in %d steps!\n", counter);
          else
              printf("No-one wins; the total is not 5\n");
          return(0);
      }
      

      显然,我故意忽略了有人可能会在输入 return 之前输入超过 4095 个字符的可能性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-26
        • 1970-01-01
        • 2012-09-07
        • 1970-01-01
        • 1970-01-01
        • 2021-05-26
        • 2020-05-18
        • 1970-01-01
        相关资源
        最近更新 更多