在 C 中比较两个相等的 unsigned long 计算结果为 false
Comparing two equal unsigned long in C evaluates to false
我是 C 的新手,正在使用它。所以我最终实现了斐波那契代码(迭代和递归)。我写了一个测试函数,它应该给我一个绿色(我的实现有效)或红色。它说我得到了正确的 return 值,但它的状态是红色的。这两个值应该都是无符号长整数。我正在使用 make
在 OSX 上编译
#include <stdio.h>
unsigned long fibonacci(unsigned long n);
void test_fibonacci(unsigned long n, unsigned long assertion);
int main(int argc, char* argv[])
{
test_fibonacci(1, 1);
test_fibonacci(2, 1);
test_fibonacci(3, 2);
test_fibonacci(10, 55);
return 0;
}
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult;
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
void test_fibonacci(unsigned long n, unsigned long assertion)
{
printf(
"fibonacci(%lu): %lu | %s | asserted: %lu\n",
n,
fibonacci(n),
(fibonacci(n) == assertion) ? "green" : "red",
assertion
);
}
我的生成文件
CFLAGS=-Wall -g
all: main
clean:
rm -f main
rm -Rf *.dSYM
输出:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 1 | red | asserted: 1
fibonacci(3): 2 | red | asserted: 2
fibonacci(10): 55 | red | asserted: 55
我没有得到你的输出。这是我看到的:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 2 | red | asserted: 1
fibonacci(3): 4 | red | asserted: 2
fibonacci(10): 3353 | red | asserted: 55
我很好奇为什么,所以我 运行 使用 valgrind。那很快就弹出这个错误:
==5619== Conditional jump or move depends on uninitialised value(s)
==5619== at 0x4005E7: test_fibonacci (fibonacci.c:31)
==5619== by 0x400559: main (fibonacci.c:9)
所以看起来这与读取未初始化的变量有关,这会给您错误的值。这最终将我们指向这里:
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult; // <---- LOOK HERE
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
注意lastResult
未初始化,但在行
中读取
result = lastResult + result;
看来您需要初始化该值。由于该值对应于先前的斐波那契数,因此您应该初始化为零。这样做会导致所有测试通过。
现在,到底发生了什么导致你看起来好像得到了正确的答案但仍然失败了?请注意,您在测试代码中调用了两次 fibonacci
。我的猜测是第一次调用 fibonacci
- 打印出来的那个 - 完全是 运行dom 的机会碰巧工作正常,因为出于某种原因第一次调用时 lastResult
中的值碰巧是 0。但是,我猜测 second 调用 fibonacci
- 与预期结果进行比较的调用 - 没有 return 与第一次调用相同的值,因为无论出于何种原因,在进行第二次调用时 lastResult
的值不是 0。这就是未定义行为的问题 - 像这样的奇怪事情可能会发生!
斐波那契 (1): 1 |绿色 |断言:1
斐波那契 (2): 3076653057 |红色 |断言:1
斐波那契 (3): 3076653058 |红色 |断言:2
斐波那契 (10): 1526988855 |红色 |断言:55
我正在将此输出添加到您的代码中。我认为这是因为未初始化的变量 lastResult。因为当我用 0 初始化它时,我得到了正确的结果。
OP 。
这表明您的测试存在细微的弱点。当 fibonacci(n)
被调用时,它提供了正确的答案。当调用 (fibonacci(n) == assertion)
时,它提供了错误的答案。缺点是您的测试代码每次测试调用 fibonacci(n)
两次而不是一次。由于您的代码有一个未初始化的变量:@templatetypedef
// unsigned long lastResult; // bad
unsigned long lastResult = 0; // good
使用 UB(未定义行为)- 这是可能的。
测试代码应该调用测试函数一次:
unsigned long f = fibonacci(n);
printf("fibonacci(%lu): %lu | %s | asserted: %lu\n",
n, f, (f == assertion) ? `"green" : "red", assertion;
那么至少,对于错误 test_fibonacci()
,获得一致结果的可能性要大得多。
OTOH,这个 弱点 指出可能是一个优势,因为如果每个循环只调用 test_fibonacci()
一次测试,UB 可能不会在方法不对。
我是 C 的新手,正在使用它。所以我最终实现了斐波那契代码(迭代和递归)。我写了一个测试函数,它应该给我一个绿色(我的实现有效)或红色。它说我得到了正确的 return 值,但它的状态是红色的。这两个值应该都是无符号长整数。我正在使用 make
在 OSX 上编译#include <stdio.h>
unsigned long fibonacci(unsigned long n);
void test_fibonacci(unsigned long n, unsigned long assertion);
int main(int argc, char* argv[])
{
test_fibonacci(1, 1);
test_fibonacci(2, 1);
test_fibonacci(3, 2);
test_fibonacci(10, 55);
return 0;
}
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult;
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
void test_fibonacci(unsigned long n, unsigned long assertion)
{
printf(
"fibonacci(%lu): %lu | %s | asserted: %lu\n",
n,
fibonacci(n),
(fibonacci(n) == assertion) ? "green" : "red",
assertion
);
}
我的生成文件
CFLAGS=-Wall -g
all: main
clean:
rm -f main
rm -Rf *.dSYM
输出:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 1 | red | asserted: 1
fibonacci(3): 2 | red | asserted: 2
fibonacci(10): 55 | red | asserted: 55
我没有得到你的输出。这是我看到的:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 2 | red | asserted: 1
fibonacci(3): 4 | red | asserted: 2
fibonacci(10): 3353 | red | asserted: 55
我很好奇为什么,所以我 运行 使用 valgrind。那很快就弹出这个错误:
==5619== Conditional jump or move depends on uninitialised value(s)
==5619== at 0x4005E7: test_fibonacci (fibonacci.c:31)
==5619== by 0x400559: main (fibonacci.c:9)
所以看起来这与读取未初始化的变量有关,这会给您错误的值。这最终将我们指向这里:
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult; // <---- LOOK HERE
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
注意lastResult
未初始化,但在行
result = lastResult + result;
看来您需要初始化该值。由于该值对应于先前的斐波那契数,因此您应该初始化为零。这样做会导致所有测试通过。
现在,到底发生了什么导致你看起来好像得到了正确的答案但仍然失败了?请注意,您在测试代码中调用了两次 fibonacci
。我的猜测是第一次调用 fibonacci
- 打印出来的那个 - 完全是 运行dom 的机会碰巧工作正常,因为出于某种原因第一次调用时 lastResult
中的值碰巧是 0。但是,我猜测 second 调用 fibonacci
- 与预期结果进行比较的调用 - 没有 return 与第一次调用相同的值,因为无论出于何种原因,在进行第二次调用时 lastResult
的值不是 0。这就是未定义行为的问题 - 像这样的奇怪事情可能会发生!
斐波那契 (1): 1 |绿色 |断言:1
斐波那契 (2): 3076653057 |红色 |断言:1
斐波那契 (3): 3076653058 |红色 |断言:2
斐波那契 (10): 1526988855 |红色 |断言:55
我正在将此输出添加到您的代码中。我认为这是因为未初始化的变量 lastResult。因为当我用 0 初始化它时,我得到了正确的结果。
OP
这表明您的测试存在细微的弱点。当 fibonacci(n)
被调用时,它提供了正确的答案。当调用 (fibonacci(n) == assertion)
时,它提供了错误的答案。缺点是您的测试代码每次测试调用 fibonacci(n)
两次而不是一次。由于您的代码有一个未初始化的变量:@templatetypedef
// unsigned long lastResult; // bad
unsigned long lastResult = 0; // good
使用 UB(未定义行为)- 这是可能的。
测试代码应该调用测试函数一次:
unsigned long f = fibonacci(n);
printf("fibonacci(%lu): %lu | %s | asserted: %lu\n",
n, f, (f == assertion) ? `"green" : "red", assertion;
那么至少,对于错误 test_fibonacci()
,获得一致结果的可能性要大得多。
OTOH,这个 弱点 指出可能是一个优势,因为如果每个循环只调用 test_fibonacci()
一次测试,UB 可能不会在方法不对。