将 float 转换为 int:复杂情况下的舍入(ceil() 和 Floor() 不可用)

发布于 2024-09-28 17:01:15 字数 298 浏览 5 评论 0原文

我想将浮点值转换为其整数表示形式。由于这将用于比较,因此默认舍入模式(round_to_nearest)不适合我。据我所知,我无法以符合 C++ 标准的方式指定 FPU 的舍入模式(即使在 C++0x 中也是如此)。还有哪些其他方法可以实现这一目标,其中哪一种最便携?我正在 Linux、GCC、i386 + x86-64 上编程。

谢谢!

编辑

我对 round_toward_infinity 和 round_toward_neg_infinity 舍入模式感兴趣,我希望每次都能选择其中一种。

I want to convert a floating point value to its integer representation. As this will be used in comparisons, the default rounding mode (round_to_nearest) is not appropriate for me. As far as I know I can't specify the rounding mode to the FPU in a C++ standard compliant way (not even in C++0x). What are the other ways to accomplish that and which one of them is the most portable? I'm programming on Linux, GCC, i386 + x86-64.

Thanks!

EDIT

I'm interested in round_toward_infinity and round_toward_neg_infinity rounding modes and I want to be able select one of them each time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

瑶笙 2024-10-05 17:01:15

如果 12.314.7 都是浮点数,那么在 IEEE 754 中 13.014.0 都是浮点数(更一般地说:给定两个非整数浮点数,其间的所有整数也是浮点数)。因此,在 IEEE 754 下,floorceil 始终正常工作(请注意,x86 使用 IEEE 754 表示)。

如果您不在 IEEE 754 下,请注意 floor 的定义是这样的(C99:7.12.9.2/3,我手头没有 C90)

floor 函数返回不大于 x 的最大整数值,以浮点数表示。

如果不能准确表示不大于 x 的最大整数值,我不知道如何解释。

If both 12.3 and 14.7 are floats then in IEEE 754 both 13.0 and 14.0 are floats (more generally: given two non-integer floats, all integers in between are floats as well). Therefore, under IEEE 754, floor and ceil always work correctly (note that x86 uses IEEE 754 representations).

If you're not under IEEE 754, note that the definition of floor says (C99:7.12.9.2/3, I don't have C90 handy)

The floor functions return the largest integer value not greater than x, expressed as a floating-point number.

I don't know how to interpret that if the largest integer value not greater than x cannot be represented exactly.

或十年 2024-10-05 17:01:15

您应该使用 floorceil。原型不是 int Floor 也不是 int ceil,但它们确实返回一个整数值。

#include <math.h>
#include <stdio.h>

int main()
{
        float x = 6.04;
        printf("floor = %f ceil = %f\n", floor(x), ceil(x));
        return 0;
}

Produces:

$ ./test 
floor = 6.000000 ceil = 7.000000

所以你现在必须说出答案。

You should use floor and ceil. The prototype is not int floor nor int ceil, but they do return an integer value.

#include <math.h>
#include <stdio.h>

int main()
{
        float x = 6.04;
        printf("floor = %f ceil = %f\n", floor(x), ceil(x));
        return 0;
}

Produces:

$ ./test 
floor = 6.000000 ceil = 7.000000

So you just now have to cast the answer.

醉态萌生 2024-10-05 17:01:15

从 C99 开始,有 llrint() 可以使用当前舍入模式(可以通过 fesetround() 设置)舍入到下一个(long long)整数。

Since C99 there's llrint() which rounds to the next (long long) integer, using the current rounding mode (that can be set by fesetround()).

后eg是否自 2024-10-05 17:01:15

您必须指定您想要的舍入类型。

用这些术语来思考:

  1. 获取一个浮点变量

  2. 适当地舍入它

  3. 转换为整数将得到整数部分浮点值 - 它截断

您可能会看floor()ceil() 分别用于向下舍入和向上舍入。

您必须特别注意 0 和负数周围发生的情况。

GLIBC 有许多舍入函数可用。

这是一个向无穷大舍入的函数:

int round_towards_infinity(double value) {
  if(value > 0)
     return ceil(value);
  return floor(value);
}

You have to specify which type of rounding you do want.

Think about it in these terms:

  1. take a floating point variable

  2. round it appropriately

  3. cast to integer will get the integer part of the floating point value - it truncates the value

You might look at floor() and ceil() for round-down and round-up respectively.

You have to pay particular attention to what you want to happen around 0 and negative numbers.

GLIBC has lots of rounding functions available.

Here's a round-towards-infinity function:

int round_towards_infinity(double value) {
  if(value > 0)
     return ceil(value);
  return floor(value);
}
水中月 2024-10-05 17:01:15

也许是这样的:

#include <cmath>

int Round( const double a )
{
  return static_cast< int >( std::floor( a + 0.5 ) );
}

Maybe like this :

#include <cmath>

int Round( const double a )
{
  return static_cast< int >( std::floor( a + 0.5 ) );
}
鸩远一方 2024-10-05 17:01:15

我一直被教导使用的转换(尽管我确信正确的浮点数学家会向我射击)是:

float x = ....;
int   y = int(x + 0.5f);

快速浏览一下我的参考资料,发现 C99 有一个采用浮点的“lrint”函数系列值并返回长整型。这可能就是您正在寻找的。

The conversion I've always been taught to use (although I'm sure proper floating point mathematicians will shoot me for it) has been:

float x = ....;
int   y = int(x + 0.5f);

A quick look through my reference says that C99 has an "lrint" family of functions that take floating point values and return long ints. It may be what you are looking for.

归属感 2024-10-05 17:01:15

听起来你需要做一些调整才能得到正确的答案。提取浮点数的指数并用它来将尾数的位模式移动正确的量。您可能需要做一些额外的技巧来处理+/-无穷大、溢出和非规范化值...但这听起来像是一条痛苦的道路..如果您真的不需要的话,我不会走它。

Sounds like you're going to have to do some bit twiddling to get the right answer. Extract the exponent of the float and use that to shift the bit pattern of the mantissa by the right amount. You may need to do some additional trickery to handle +/- infinity and overflows and denormalised values... but it sounds like a painful path.. I'd not walk it if you really didn't have to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文