如何做偏差的浮点舍入(总是向上或向下)? [英] How do I do floating point rounding with a bias (always round up or down)?

查看:153
本文介绍了如何做偏差的浮点舍入(总是向上或向下)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要有偏差的圆形浮标,要么总是向下,要么总是向上。代码中有一个特定的点,我需要这个,其余的程序应该像往常一样舍入到最接近的值。

I want to round floats with a bias, either always down or always up. There is a specific point in the code where I need this, the rest of the program should round to the nearest value as usual.

例如,我想舍入最近的1/10倍数。最接近7/10的浮点数约为0.69999998807,但最接近8/10的数字约为0.80000001192。当我舍入数字,这是我得到的两个结果。我宁愿让他们圆相同的方式。 7/10应该舍入到0.70000004768和8/10应舍入到0.80000001192。

For example, I want to round to the nearest multiple of 1/10. The closest floating point number to 7/10 is approximately 0.69999998807, but the closest number to 8/10 is approximately 0.80000001192. When I round off numbers, these are the two results I get. I'd rather get them rounded the same way. 7/10 should round to 0.70000004768 and 8/10 should round to 0.80000001192.

在这个例子中,我总是向上舍入,但我有一些地方,我想永远向下舍入。幸运的是,我只处理这些地方的正值。

In this example I am always rounding up, but I have some places where I want to always round down. Fortunately, I am only dealing with positive values in each of these places.

我使用的行是 floor(val * 100 + 0.5)/ 100 。我在C ++编程。

The line I am using to round is floor(val * 100 + 0.5) / 100. I am programming in C++.

推荐答案

我认为实现这一点的最好方法是依赖于这样的事实,根据IEEE 754浮点标准,浮点位的整数表示按字母顺序排列为2补码整数。

I think the best way to achieve this is to rely on the fact that according to the IEEE 754 floating point standard, the integer representation of floating point bits are lexicographically ordered as a 2-complement integer.

你可以简单地添加一个ulp(单位在最后一个位置)以获得下一个浮点表示(如果它更小,它将总是略大于你的阈值,因为轮回误差至多为1/2 ulp)

I.e. you could simply add one ulp (units in the last place) to get the next floating point representation (which will always be slightly larger than your treshold if it was smaller, since the round error is at most 1/2 ulp)

例如

 float floatValue = 7.f/10;
 std::cout << std::setprecision(20) << floatValue << std::endl;
 int asInt = *(int*)&floatValue;
 asInt += 1;
 floatValue = *(float*)&asInt;
 std::cout << floatValue << std::endl;

打印(在我的系统上)

 0.69999998807907104492
 0.70000004768371582031

添加一个ulp,你将不得不依赖 floor 和舍入 floor的区别

To know when you need to add one ulp, you'll have to rely on the difference of floor and a rounded floor

 if (std::floor(floatValue * 100.) != std::floor(floatValue * 100. + 0.5)) {
    int asInt = *(int*)&floatValue;
    asInt += 1;
    floatValue = *(float*)&asInt;
 }

将0.69 ..正确转换为0.70 .. 。

Would correctly convert 0.69.. to 0.70.. but leave 0.80.. alone.

请注意,通过与 100的乘法将浮点数提升为double。<$ c $应用c> floor

如果不这样做,您可能会遇到

If you don't do this you risk getting in the situation that for

 7.f/10.f * 100.f



<浮动表示将是70.00 ...

The (limited in precision) float representation would be 70.00...

这篇关于如何做偏差的浮点舍入(总是向上或向下)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆