为什么我在这个简单的C程序上得到这个奇怪的输出?
我正在做一个个人项目,其中一部分是计算某个界限下的正方形和立方体(本例中为10000)。所以,我写了一个简单的C程序,我认为可以用来验证我的结果。下面是我为查看所有立方体而编写的小程序:为什么我在这个简单的C程序上得到这个奇怪的输出?,c,C,我正在做一个个人项目,其中一部分是计算某个界限下的正方形和立方体(本例中为10000)。所以,我写了一个简单的C程序,我认为可以用来验证我的结果。下面是我为查看所有立方体而编写的小程序: #include <stdlib.h> #include <stdio.h> #include <math.h> int main() { double i; int cubes = 0; for (i = 1; i < 10
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main() {
double i;
int cubes = 0;
for (i = 1; i < 10000; i++) {
if ( i == cbrt(i) * cbrt(i) * cbrt(i) ) {
printf("%f --- %f\n",i, cbrt(i));
cubes++;
}
}
printf("%i\n", cubes);
return 0;
}
#包括
#包括
#包括
int main(){
双i;
整数立方=0;
对于(i=1;i<10000;i++){
如果(i==cbrt(i)*cbrt(i)*cbrt(i)){
printf(“%f---%f\n”,i,cbrt(i));
cubes++;
}
}
printf(“%i\n”,立方体);
返回0;
}
我得到了(不正确的)输出:24。如果您想查看此问题,请查看输出上的数字15和20。为什么我会得到错误的答案(正确答案是21)是一个完全不同的问题。我的问题出现在我尝试修复代码时,我临时将其更改为:
int main() {
double i;
int cubes = 0;
for (i = 1; i < 10000; i++) {
double temp = (cbrt(i) * cbrt(i) * cbrt(i));
if ( i == temp ) {
printf("%f -> %f\n", i, temp);
cubes++;
}
}
printf("%i\n", cubes);
return 0;
}
intmain(){
双i;
整数立方=0;
对于(i=1;i<10000;i++){
双温=(cbrt(i)*cbrt(i)*cbrt(i));
如果(i==temp){
printf(“%f->%f\n”,i,temp);
cubes++;
}
}
printf(“%i\n”,立方体);
返回0;
}
现在,程序正在打印1到9999之间的每个数字。那么,我是不是错过了一些非常简单的事情,或者是发生了什么?我所做的只是在if条件中设置一个等于result的双变量,并将其放置在条件中,而不是使用cbrt(I)*cbrt(I)*cbrt(I)
。为什么我的程序要这样做
我不知道这件事为什么会被否决。我觉得这是一个合理的问题。抱歉,S.O.社区…双cbrt(双x)
返回最接近的x的可表示立方根
结果的不精确性,然后乘以三次,可能不会再次完全等于“x”
第二个计划的不同之处:
C不必仅为double
精度执行double
数学运算。它可以使用更宽的(long double
)。根据不同的情况,第二个代码在长双精度中比第一个代码做得更多。通过额外的精度,很容易看出四舍五入到double
的结果是精确的
C11dr§5.2.4.2.2 9,分配和施法(消除所有额外范围和精度)除外,带有浮点操作数的运算符和经过常规算术转换的值以及浮点常量的值将计算为一种范围和精度可能大于类型要求的格式
为什么一个典型的程序运行(任一代码)会产生大约3333的结果
考虑从2到4和从8到64的双
数字double
数字是对数分布的。从2到4,从8到16,从16到32,从32到64,有许多不同的double
所以现在从8到64的所有3个集合都有一个2到4的1集合中某个答案的立方根。现在如果我们把数字2到4进行立方运算,我们得到的答案在8到64之间。1组数字映射为3组。往返行程不准确。看见IOW:平均而言,8到64之间的3个数字具有相同的立方根。然后,该根的立方体将是3个原始根中的1个
求0到N的完美整数立方体的计数
unsigned Perfect_Cube_Count(unsigned n) {
if (n == 0)
return 1;
unsigned i;
// overflow not possible
for (i = 0; i*i < n/i; i++);
return i;
}
无符号完美立方体计数(无符号n){
如果(n==0)
返回1;
未签名的i;
//不可能溢出
对于(i=0;i*i
或
//对于0有效,正如Andrew猜测的那样,您可能想要整数立方根。由于舍入误差,浮点运算相当棘手。通常,您不能依赖于相等,但必须与误差幅度进行比较
为了解决你的问题,我会事先构造21个立方体,然后对整数进行迭代,与预先构造的立方体进行比较。还是作弊?;-)
塞缪尔·贝克特(Samuel Becket)的小说《瓦特》(Watt)中有一章是关于一位苏格兰“数学天才”的,他能在头脑中计算出整数立方的所有整数三次方根,最大可达10000个左右 我的问题是,您的编译器在第二种情况下进行了优化,省略了cbrt调用。它只是说cbrt的结果是由标准严格定义的,所以它也可能总是(i==temp)
您可以通过一些命令行参数来实现这一点,并强制它完全按照代码中所写的操作。我记得,这应该是C编译器在浮点运算方面的默认做法,但您的编译器可能认为它比您或其他人更聪明
编辑
是的,这段代码与寻找完美立方体无关
编辑
这完全不是问题的答案,但作为一个快速练习,我写了以下内容:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
static unsigned long count_cubes(unsigned long max_n)
{
unsigned long n = 1;
while (n*n*n <= max_n) {
++n;
}
return n-1;
}
int main(int argc, char **argv)
{
unsigned long max_n;
char *p;
if (argc < 2) {
return EXIT_FAILURE;
}
max_n = strtoul(argv[1], &p, 10);
if (max_n < 1 || max_n == ULONG_MAX) {
return EXIT_FAILURE;
}
printf("%lu\n", count_cubes(max_n));
return EXIT_SUCCESS;
}
这两个数字显然没有相同的立方根,但是cbrt
返回相同的结果。在这种情况下,floor
也没有帮助。不管怎么说,使用浮点运算总是需要非常小心。现在我真的该睡觉了。你到底想在这里干什么?您是否正在尝试查找具有整数立方根的数字?第一印象-您正在检查浮点数(double
)是否相等,这只是在查找问题。为什么不改用simpleint
?或者uint64\u t
,或者其他任何东西。假设i是int,temp是double,由于double的内部舍入,您通常无法实现相等。@dboals数学上是“(X的立方根)cubed等于X”,但是,double
的有限精度阻止了精确的解决方案。@user3270407希望您所有的问题都得到了回答。这仍然不能向我解释“程序正在打印1到9999之间的每个数字”的行为。OP在循环结束时打印一个计数,这将很难忽略这个问题
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
static unsigned long count_cubes(unsigned long max_n)
{
unsigned long n = 1;
while (n*n*n <= max_n) {
++n;
}
return n-1;
}
int main(int argc, char **argv)
{
unsigned long max_n;
char *p;
if (argc < 2) {
return EXIT_FAILURE;
}
max_n = strtoul(argv[1], &p, 10);
if (max_n < 1 || max_n == ULONG_MAX) {
return EXIT_FAILURE;
}
printf("%lu\n", count_cubes(max_n));
return EXIT_SUCCESS;
}
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <math.h>
static unsigned long count_cubes(unsigned long max_n)
{
unsigned long n;
if (max_n < 256) {
n = 1;
}
else {
n = cbrtl(max_n) - 1;
}
while (n*n*n <= max_n) {
++n;
}
return n-1;
}
int main(int argc, char **argv)
{
unsigned long max_n;
char *p;
if (argc < 2) {
return EXIT_FAILURE;
}
max_n = strtoul(argv[1], &p, 10);
if (max_n < 1 || max_n == ULONG_MAX) {
return EXIT_FAILURE;
}
printf("%lu\n", count_cubes(max_n));
return EXIT_SUCCESS;
}
printf("%f\n", cbrt( 2642245UL * 2642245UL * 2642245UL));
/* prints 2642245.000000 */
printf("%f\n", cbrt( 2642245UL * 2642245UL * 2642245UL - 10UL));
/* prints 2642245.000000 */