我非常喜欢WxWidgets,并开始使用C ++编程。我的示例程序将Celsius从文本形式转换为Fahrenheit。这是我的基本代码:
//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,但是它返回的是华氏度而不是212而不是212!奇怪的是,公式在纯C中运行良好,当我用lCelsius
替换100
时,它工作正常,即使我的调试信息清楚地表明它是100。
你看到任何明显的问题,还是我不能做这么简单的事情?我不确定Wx正在做些什么来使它比它应该少一些。
编辑:包括assert.h和运行lCelsius == 100在调试器中失败,但是std :: cout lCelsius返回100.必须有一些Wx结果,但仍然是“100” ..
答案 0 :(得分: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 :(得分:1)
您可以尝试在程序集级别对此进行调试,以更详细地了解正在进行的操作。
此外,正如一个风格的建议,主要术语可以写成(9.f / 5.f)
,摆脱演员阵容,更容易阅读。
我也质疑为什么你使用long
作为温度,对我而言,感觉好像大多数温度(尤其是华氏温度)都在普通int
支持的范围内。