WxWidgets:简单的数学公式给出错误的结果?

问题描述 投票:0回答:2

我非常喜欢WxWidgets,并开始在其中进行C++编程。我的示例程序将摄氏温度从文本形式转换为华氏温度。这是我的基本代码:

//get "100" from textbox
wxString szCelsius = TextCtrl1->GetValue();
long lCelsius;

//attempt to cast into long
szCelsius.ToLong(&lCelsius, 10);

//formula that works in normal cases to get fahrenheit
long lFahrenheit = ((9.f/5.f) * lCelsius + 32);

//SOMEHOW this works:
//long lFahrenheit = ((9.f/5.f) * 100 + 32);

//display debug info, note it displays lCelsius as 100
wxString debuginfo;
debuginfo << _T("deg C: ")  << lCelsius << _T("\n");
//displays incorrectly as 211
debuginfo << _T("deg F: ") << lFahrenheit << _T("\n");
//this displays 100
std::cout << lCelsius;
//this fails though
assert(lCelsius == 100);

现在有了调试信息,lCelcius 与预期一样为 100,但它返回华氏度为 211 而不是 212!奇怪的是,公式在纯 C 中工作得很好,当我用

lCelsius
替换
100
时,它工作得很好,即使我的调试信息清楚地表明它是 100。

您是否发现任何明显的问题,或者我只是无法做这么简单的事情?我不太确定 Wx 正在做什么来使其比应有的值少 1。

编辑:包括assert.h并在调试器中运行lCelsius == 100失败,但std::cout lCelsius返回100。Wx一定有什么问题正在破坏结果,但仍然是“100”..

c++ c type-conversion wxwidgets
2个回答
3
投票

值 1.8(即 9/5)无法精确表示为二进制浮点数 - 在二进制中,它是一系列重复出现的数字(1.1100110011001100110011001100...) - 类似于十进制中 1/3 的重复出现.

最接近的单精度浮点值表示形式略低于 1.8 - 大约为 1.7999999523)。 当这个数字乘以 100 时,得到的值略低于 180;然后加上 32,得到的数字略低于 212。

将浮点数转换为整数会截断小数部分,因此 211.999... 变为 211。

如果您在源代码中使用文字 100,而不是运行时提供的值,则不会发生这种情况,因为编译器在编译时将表达式

(9.f/5.f) * 100
简化为简单的 180。

如果您的编译器支持 C99

roundf()
函数(在
math.h
中声明),您可以使用它来舍入到最接近的整数:

long lFahrenheit = roundf((9.f/5.f) * lCelsius + 32);

1
投票

您可以尝试在程序集级别进行调试,以更详细地了解发生了什么。

此外,作为一种风格建议,主导术语可以写成

(9.f / 5.f)
,这样可以消除强制转换并且更易于阅读。

我还质疑为什么你使用

long
作为温度,对我来说,感觉好像大多数温度(特别是涉及华氏度)都在普通
int
支持的范围内。

© www.soinside.com 2019 - 2024. All rights reserved.