我是编程新手。我在c中使用sqrt()
函数找到了数字的平方根。 `
scanf("%d", &n);
printf("%d\n", sqrt(n));
}
return 0;
}
当我输入n = 5
的值时,我得到了一些负数。有人可以解释一下吗?
答案 0 :(得分:4)
您通过将错误的类型传递给printf
来产生未定义的行为:%d
格式需要类型int
的匹配参数,但您的参数类型为double
}。您需要%f
(或%e
或%g
或%a
)进行打印。此外,可能存在其他问题,例如,如果你省略了#include <math.h>
。
答案 1 :(得分:1)
正如其他人所指出的,这里的问题是格式说明符是错误的。您需要#include <math.h>
才能获得sqrt()
的正确返回类型,然后使用格式说明符%f
。此外,打开编译器警告,直到它告诉你这里有什么问题。 -Wall -Wextra -pedantic -Wno-system-headers
是个不错的选择。
我正在添加一个答案,以提供有关float
变量在double
参数列表中被提升为printf()
的原因的历史背景,而不是scanf()
,因为在评论中这让人困惑。
在最初开发C的DEC PDP-10和PDP-11计算机的指令集中,float
类型仅存在以节省空间,并且需要转换{{1}的程序} float
对其进行任何计算。在早期版本的C中,在ANSI函数原型之前,函数的所有double
参数在传递之前自动提升为float
(并且double
也传递给char
)。最初,这在较低级别上运行得更好,并且还具有使用较短类型避免数学上的舍入和溢出错误的优点。该约定还简化了编写函数,这些函数采用了不同类型的不同参数,例如int
。调用者可以传递任何内容,编译器会允许它,并且调用函数的工作就是弄清楚参数列表在运行时应该是什么。
当C添加函数原型时,这些旧规则仅用于遗留函数声明(printf()
而不是extern double sqrt()
或C14通用等价物)以保持向后兼容性。由于基本上没有人以这种方式编写函数,这是一个历史性的好奇心 - 有一个例外。像extern double sqrt(double)
这样的varargs
函数不能用C语言编写,并对变量参数进行类型检查。 (使用模板有一种C ++方法可以做到这一点。)标准委员会也不想破坏打印int printf(const char*, ...);
的所有现有代码。所以那些仍然按照旧规则进行推广。
在float
中,这都不适用,因为存储参数是通过引用传递的,而scanf()
需要确保它以与保存它的变量相同的类型写入数据。争论促销永远不会发挥作用,因为只有指针才能通过。
答案 2 :(得分:1)
我遇到同样的问题。我想获得int
类型的答案。我使用强制类型转换,例如:
printf("%d\n", (int)sqrt(n));
答案 3 :(得分:0)
之所以会这样,是因为未指定sqrt()的返回类型和输入类型, 您可以通过以下方式解决此问题:
#include<math.h>
或通过明确指定返回和输入类型,例如
:double sqrt(double);
并且如上所述,请使用正确的格式说明符(例如:%f)。