判断浮点数是否有小数部分?

13

问题如下:游戏"Totals"可以由任意数量的人玩。它以100为总数开始,每个玩家依次对该总数进行-20到20之间的整数位移。赢家是使总数等于5的玩家。只使用所给出的三个变量: total adjustment counter 这是我目前的代码:

#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语句中。如何确定浮点数是否有小数部分。


在二进制级别上,没有浮点数有小数点。http://en.wikipedia.org/wiki/IEEE_754-2008 - Chris Eberle
我们在讨论浮点数。它总是“有小数”。使用double代替。(顺便说一下,@Chris和我意思相同) - Tom van der Woerdt
2
@TomvanderWoerdt:使用double有什么不同? - Oliver Charlesworth
@OliCharlesworth 所有人都告诉我,double 和 float 的区别在于 float 会有精度误差,而 double 可以存储更少的数据。如果我错了,请纠正我。 - Tom van der Woerdt
3
纯属好奇,为什么程序里还要包含一个float呢?明明只有整数相关的内容。 - Daniel Fischer
显示剩余2条评论
5个回答

26
你可以将 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 时,显然它们不是相同的值,因此将输出“fractional!”。


2
你不需要显式地将 float 转换回去,它会自动转换。你的解决方案并没有错,我只是会将其写成 f == (int)f,我觉得这样更易于阅读和理解。 - Kevin
@Kevin 我在你发表评论的同时进行了编辑,然后添加了更多有关此事的信息,谢谢。 - Filip Roséen - refp
3
我并不认为所有使用这种技术的答案都是健壮的。如果adj实际上是中间计算的结果,它可能会被保存在扩展精度寄存器中。因此,即使当稍后检查adj时,它实际上是一个整数值,比较也可能返回false - Oliver Charlesworth
2
你确定这个代码完全可行吗?将14作为浮点数表示时,实际上会被表示成大约13.9999239894。因此,比较操作大多数情况下都会失败。 - tothphu
令人费解的是,这个答案竟然有26个赞!但是这个方法根本行不通! - Alex D

15
#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不会对那些不能表示的数字出现误差。 - lhf
谢谢您提供更详细的答案。 :) - sarnold
我并不认为所有使用这种技术的答案都是健壮的。如果adj实际上是中间计算的结果,它可能会被保存在扩展精度寄存器中。因此,即使当稍后检查adj时,它实际上是一个整数值,比较也可能返回false - Oliver Charlesworth

1

我只是在学习C语言,如果我有错误,请告诉我。

但是,如果我们不使用

scanf("%f",&adj);

如果你使用:

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

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

也许吧。


0

使用scanf()存在问题。如果用户在第一行输入-5 +10 -15 -15,然后按回车键,你将使用scanf()逐个处理这4个数字。这可能不是你想要的结果。当然,如果用户输入+3或更多,那么第一个转换会在读取空格时停止,并且所有后续转换都会在oor处失败,代码进入循环。你必须检查scanf()的返回值,以知道它是否能够转换任何内容。

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

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

#include <math.h>

double modf(double x, double *iptr);
float modff(float value, float *iptr);

返回值是 x 的带符号小数部分;iptr 中的值是整数部分。请注意,如果编译器(运行时库)不支持 C99,则可能无法使用 modff()。在这种情况下,您可能需要使用 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);
}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接