用C ++安全地重新缩放和向下转换浮点数

时间:2018-02-19 16:04:26

标签: c++ downcast

我正在尝试将一个浮点数R加起来,我希望以无符号8位整数格式获取其权重wt

float R;
float edgeVal = rintf(R); // round to the nearest edge
float dR = R - edgeVal + 0.5f; // distance to the edge with a half-pixel offset
unsigned char wt = static_cast<unsigned char>( dR*256.f )); // allowed range [0; 255]

dR == 0.f的间隔边缘,我们将获得wt=0,但在dR == 1.f的另一边,我们将获得wt = 256 0,虽然我们真的想在这种情况下获得wt = 255。什么是实现它的正确代码?

以下是变量范围的2位示例:

wt = |0|1|2|3|
     ^       ^
     |       |
dR = 0       1

1 个答案:

答案 0 :(得分:2)

如果只是1.0f的确切值,那么您可能希望首先避免为dR获取此值。我建议对您的逻辑进行微小更改,将rintf替换为floor,其行为在所有情况下都可以很容易地预测,而不受任何外部因素的影响:

float Radj = R + 0.5f;
float edgeVal = floor(R); // now Radj - 1 < edgeVal <= Radj
float dR = Radj - edgeVal; // 0 <= dR < 1

现在原来的

static_cast<unsigned char>( dR*256.f ));

永远不会溢出到0。

对于一些测试值,原始代码给出

R       edgeVal dR  wt
0       0       0.5     128
0.25    0       0.75    192
0.5     0       1       0
0.75    1       0.25    64
1       1       0.5     128
1.25    1       0.75    192
1.5     2       0       0
1.75    2       0.25    64
2       2       0.5     128

floor edgeValwt的值保持一致(以调整前者为代价):

R       edgeVal dR  wt
0       0       0.5     128
0.25    0       0.75    192
0.5     1       0       0       // note the change here
0.75    1       0.25    64
1       1       0.5     128
1.25    1       0.75    192
1.5     2       0       0
1.75    2       0.25    64
2       2       0.5     128