如何为浮点数指定舍入模式?

时间:2015-01-24 03:24:21

标签: floating-point rust rounding

我希望将浮点数舍入到最接近的整数,当与#34;最接近的整数"相关时,朝向正无穷大。

use std::num::Float;

fn main() {
    assert_eq!(-0.0, (-0.5).round()); // fails!
}

但是,round的文档说:

  

远离0.0的圆形中途案例。

我还没有看到任何可以让我改变舍入模式的东西,但是必须有某种方式,对吧?

2 个答案:

答案 0 :(得分:6)

Float::round的实施,至少对f32f64的实施似乎转发到roundf32 / roundf64个教义,这些教育本身已经实施使用LLVM函数llvm.round.f32llvm.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))

快速解释发生了什么:

  1. floor找到小于或等于x的最接近的整数。
  2. 如果y==x,那么x是一个整数,因此不需要进行舍入:请注意,这会捕获x的绝对值大于2 的所有情况。
  3. floor(2*x-y)会给出所需的答案:2*x是准确的,我们不必担心因第2步而导致的溢出。除{{1}之外的所有情况下,减法都是准确的。无论如何,这显然会给出正确答案。
  4. -0.25 < x < 0只是为了确保零符号正确。如果你不被这些事情困扰,你可以把它关掉。
  5. 步骤2&amp; 3可以用简单的分支代替:

    copysign

    但是如果我没记错的话,在这里避开分支会使代码更符合矢量化(这也是使用x-y < 0.5 ? y : y+1.0 代替ifelse块的原因。)