将 float 转换为 int:复杂情况下的舍入(ceil() 和 Floor() 不可用)
我想将浮点值转换为其整数表示形式。由于这将用于比较,因此默认舍入模式(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果
12.3
和14.7
都是浮点数,那么在 IEEE 754 中13.0
和14.0
都是浮点数(更一般地说:给定两个非整数浮点数,其间的所有整数也是浮点数)。因此,在 IEEE 754 下,floor
和ceil
始终正常工作(请注意,x86 使用 IEEE 754 表示)。如果您不在 IEEE 754 下,请注意
floor
的定义是这样的(C99:7.12.9.2/3,我手头没有 C90)如果不能准确表示不大于 x 的最大整数值,我不知道如何解释。
If both
12.3
and14.7
are floats then in IEEE 754 both13.0
and14.0
are floats (more generally: given two non-integer floats, all integers in between are floats as well). Therefore, under IEEE 754,floor
andceil
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)I don't know how to interpret that if the largest integer value not greater than x cannot be represented exactly.
您应该使用 floor 和 ceil。原型不是 int Floor 也不是 int ceil,但它们确实返回一个整数值。
Produces:
所以你现在必须说出答案。
You should use floor and ceil. The prototype is not int floor nor int ceil, but they do return an integer value.
Produces:
So you just now have to cast the answer.
从 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 byfesetround()
).您必须指定您想要的舍入类型。
用这些术语来思考:
获取一个浮点变量
适当地舍入它
转换为整数将得到整数部分浮点值 - 它截断值
您可能会看
floor()
和ceil()
分别用于向下舍入和向上舍入。您必须特别注意 0 和负数周围发生的情况。
GLIBC 有许多舍入函数可用。
这是一个向无穷大舍入的函数:
You have to specify which type of rounding you do want.
Think about it in these terms:
take a floating point variable
round it appropriately
cast to integer will get the integer part of the floating point value - it truncates the value
You might look at
floor()
andceil()
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:
也许是这样的:
Maybe like this :
我一直被教导使用的转换(尽管我确信正确的浮点数学家会向我射击)是:
快速浏览一下我的参考资料,发现 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:
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.
听起来你需要做一些调整才能得到正确的答案。提取浮点数的指数并用它来将尾数的位模式移动正确的量。您可能需要做一些额外的技巧来处理+/-无穷大、溢出和非规范化值...但这听起来像是一条痛苦的道路..如果您真的不需要的话,我不会走它。
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.