2

我同时使用了 Ogre 和 NxOgre,它们都有一个Realtypedef,它要么float取决于编译器标志,要么double取决于编译器标志。这导致我们的大多数编译器警告现在是:

warning C4305: 'argument' : truncation from 'double' to 'Ogre::Real'

例如,当使用 0.1 初始化变量时。通常我会使用 0.1f 但如果您将编译器标志更改为双精度,那么您会收到反向警告。我想最好选择一个并坚持下去,但如果可能的话,我想以一种适用于任何一种配置的方式编写这些。

一种解决方法是#pragma warning (disable : 4305)在它发生的文件中使用,我不知道是否还有其他更复杂的问题可以通过没有此警告来隐藏。我知道我也会在头文件中推送和弹出这些内容,以免它们最终传播到代码中。

另一种是根据准确度编译器标志创建一些宏,例如:

#if OGRE_DOUBLE_PRECISION
    #define INIT_REAL(x) (x)
#else
    #define INIT_REAL(x) static_cast<float>( x )
#endif

这将需要更改到目前为止完成的所有变量初始化,但至少它将是未来的证明。

任何偏好或我没有想到的东西?

4

4 回答 4

3

简单的解决方案是只添加一个演员:

static_cast<Ogre::Real>(0.1);

或者您可以编写一个函数来为您进行转换(类似于您的宏,但避免宏带来的所有令人讨厌的问题:

template <typename T>
inline Ogre::Real real(T val) { return static_cast<Ogre::Real>(val); } 

然后你可以调用real(0.1)并获取值作为Ogre::Real.

于 2010-05-25T13:03:49.560 回答
1

显然,如果您使用的类型是特定于平台的,那么文字也应该如此。使用 TCHARs、CStrings、LPCTSTRs 等时会出现同样的问题...,更糟糕的是:char无法转换为wchar_t.

所以我的偏好肯定是初始化宏。忽略警告是危险的。

你甚至可以指定你的宏来附加“float”文字标签​​:

//#define DOUBLEPREC

#ifndef DOUBLEPREC
typedef float REAL;
#define INIT_REAL(r) (r##f)
#else
typedef double REAL;
#define INIT_REAL(r) r
#endif

REAL r = INIT_REAL(.1);
double d = INIT_REAL(.1);
float f = INIT_REAL(.1);
于 2010-05-25T11:51:31.933 回答
1

始终使用浮点文字进行初始化。每个浮点值都有一个表示完全相同的十进制数的双精度值(尽管这可能不是浮点数打算表示的十进制值的最佳双精度近似值)。

Visual Studio 似乎在编译时执行扩展,即使在调试版本中,虽然结果并不完全鼓舞人心:将 1.1f 传递给一个函数,该函数需要双传递 1.1000000238418579,但在传递 1.1000000000000001 时传递 1.1。(根据观察窗口的两个值。)

(当然,对于具有精确表示的数字,例如 1.25f,没有这样的问题。)

这是否是一个大问题,我不能说,但如果你的游戏在浮点数上运行良好,那么它已经可以容忍类似程度的不准确性。

于 2010-05-25T20:22:40.827 回答
0

至于我,我会坚持其中一种类型而忘记这个警告。无论如何,双精度/单精度对 fps 的影响很小(在我的项目中小于 3%)。

还要提一下(据我所知),DirectX 和 OpenGL 以单精度工作。

如果你真的想以正确的方式摆脱这个警告,你可以使用这些#if东西,但不是你以前的方式。更好的方法是制作类似的东西

#if OGRE_DOUBLE_PRECISION == 1
    // Note that 
    typedef double Real;
#else
    typedef float Real;
#endif

你也可以使用 Ogre::Real 作为类型来编写你的代码(或者对它进行类型定义,这样你会觉得舒服)。

于 2010-05-25T11:57:39.573 回答