我希望将浮点数舍入到最接近的整数,当与#34;最接近的整数"相关时,朝向正无穷大。
use std::num::Float;
fn main() {
assert_eq!(-0.0, (-0.5).round()); // fails!
}
但是,round
的文档说:
远离0.0的圆形中途案例。
我还没有看到任何可以让我改变舍入模式的东西,但是必须有某种方式,对吧?
答案 0 :(得分:6)
Float::round
的实施,至少对f32
和f64
的实施似乎转发到roundf32
/ roundf64
个教义,这些教育本身已经实施使用LLVM函数llvm.round.f32
和llvm.round.f64
。遗憾的是,documentation for llvm.round.*
没有说明如何控制舍入模式。 LLVM引用中似乎没有任何其他内容。我可以找到的其他函数甚至提到舍入模式指定一个特定的舍入模式,或者说它是未定义的。
我找不到任何关于此的可靠信息。有a post on the LLVM mailing list from 2011讨论x86特定的内在函数,而2013 post to the Native Client issue tracker似乎谈论了一个假设的内在函数以及它如何易于移植。
盲目地捅它:我会尝试编写一个小C库,然后链接到那个。它似乎没有在LLVM中直接支持。
答案 1 :(得分:2)
我害怕我不知道Rust,但是我写了下面的for Julia(基于类似的序列,以便与Arch Robinson保持一致),你应该能够适应:
y = floor(x)
ifelse(x==y, y, copysign(floor(2*x-y),x))
快速解释发生了什么:
floor
找到小于或等于x
的最接近的整数。y==x
,那么x
是一个整数,因此不需要进行舍入:请注意,这会捕获x
的绝对值大于2 的所有情况。 floor(2*x-y)
会给出所需的答案:2*x
是准确的,我们不必担心因第2步而导致的溢出。除{{1}之外的所有情况下,减法都是准确的。无论如何,这显然会给出正确答案。-0.25 < x < 0
只是为了确保零符号正确。如果你不被这些事情困扰,你可以把它关掉。步骤2&amp; 3可以用简单的分支代替:
copysign
但是如果我没记错的话,在这里避开分支会使代码更符合矢量化(这也是使用x-y < 0.5 ? y : y+1.0
代替ifelse
块的原因。)