【问题标题】:log function misbehaviour!!! Any clue?记录功能不当行为!!!有什么线索吗?
【发布时间】:2010-08-18 16:26:34
【问题描述】:

我正在用 C 语言编写一些程序。它有一部分用于进行概率计算,我正在使用 log 函数。普通库函数 log()...

代码是这样的

double somevalue = 0.29558101472995091;
temp = log(somevalue)

你猜怎么着?温度值 -1856.0000000000000!!!

由于给定的 log 值在某个结构中,所以我也编写了这个测试代码,并得到了相同的结果...

int main()
{
    double somevalue;
    double temp;

    somevalue = 0.29558101472995091;
    temp = log(somevalue);
    return 0;
}

Results:
Somevalue = 0.29558101472995091
temp = -1856.0000000000000

是不是很疯狂。任何人都知道这里发生了什么。

我正在为此使用 Visual Studio 2005。我现在无法使用其他编译器。

谢谢,

微内核:)

【问题讨论】:

  • 您如何检查 temp 的值?错误地使用 printf 比 log() 函数出错的可能性更大
  • 供参考:log(0.29) = about -0.5
  • @mmyers:嗯?应该是-1.2188...
  • @mmyers: log 计算自然对数,而不是基于 10 的对数!
  • 您的示例程序不打印/显示任何结果。你怎么看结果?您是否能够生成一个可独立编译的示例,在屏幕上打印出错误的结果?编写的代码看起来是正确的。如果您在调试器中查看结果,如果构建已优化,则可能会误解它们。

标签: c++ c visual-c++ visual-studio-2005


【解决方案1】:

您需要#include <math.h>,以便编译器正确调用log()

使用 VC10,当包含 math.h 时,我从 printf ("log(%lf) = %lf\n", somevalue, temp ) 得到以下结果:

log(0.295581) = -1.218812

如果不包括math.h,我会得到:

log(0.295581) = -1856.000000

可能发生的情况是编译器期望调用log() 的返回值为int,然后将其转换为double 以存储在temp 中。我不知道编译器如何返回浮点结果,但我猜它们会在 FP(0) 寄存器中返回,而在 EAX 中返回 int 结果(假设 x86 Win32 平台)。因此,在这种情况下,编译器获取的值甚至可能与 log() 函数试图返回的值没有任何关系。

如果您将警告级别设置为/W3,您将收到有关该问题的警告:

C:\TEMP\test.c(10) : warning C4013: 'log' undefined; assuming extern returning int

在我看来,除非你正在使用一个不利用函数原型的非常旧的代码库,否则将警告变成错误可能是很有意义的(当然,当编译为 C++ 时,这已经是一个错误):

#pragma warning( error : 4013) // or use the `/we4013` compiler option

这是可编译的测试:

#include <stdio.h>
//#include <math.h>

int main()
{
    double somevalue;
    double temp;

    somevalue = 0.29558101472995091;
    temp = log(somevalue);

    printf ("log(%lf) = %lf\n", somevalue, temp);

    return 0;
}

【讨论】:

  • 这个问题不应该有 C++ 标签,因为它不允许使用“隐式 int”调用未声明的函数。
  • 哇!真的是这个原因!!!我想知道编译器在做什么,如果它找不到正确的日志函数!!!如果找不到合适的功能,我会预料到链接器会出错.... 哈,即使在 C 语言中编码了 2 年后,我真是个菜鸟!!!谢谢迈克尔,它有很大帮助!!! :)
  • @Microkernel 我相信如果您将其编译为 C++ 甚至 ANSI C,则此代码不会编译。
  • 为什么有人会将他们的警告级别低于默认值?它应该在 /W4。
  • 实际上,比这更糟糕。如果假定返回类型是和int 而不是double,那么double 甚至不会被读取为int;甚至可以从错误的地方读取返回值。 IIRC,在许多 x86 调用约定中,浮点值在 %st(0) 中返回,而整数返回值在 %eax 中返回,因此它可能是随机垃圾,被读取为 int 返回。
【解决方案2】:

看起来你的语法是正确的。你是如何打印你的结果的?如果您使用的是 printf 语句,请确保您的格式字符串正确。

它应该像this example

printf ("log(%lf) = %lf\n", somevalue, temp );

【讨论】:

  • 不,它通过 cout 和上述声明给我 -1.21881。
  • 不,我在单步执行程序时使用了监视窗口...感谢您的回复:)
猜你喜欢
  • 2011-01-06
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2015-03-27
  • 2010-12-28
  • 1970-01-01
相关资源
最近更新 更多