如何指定浮点数的舍入方式?
How do I specify the rounding mode for floating point numbers?
我想将浮点数舍入到最接近的整数,当 "nearest integer" 并列时趋于正无穷大。
use std::num::Float;
fn main() {
assert_eq!(-0.0, (-0.5).round()); // fails!
}
然而,round
的文档说:
Round half-way cases away from 0.0.
我还没有看到任何可以让我改变舍入模式的东西,但总有一些方法,对吗?
看起来 Float::round
的实现,至少对于 f32
和 f64
,转发到 roundf32
/roundf64
内部函数,它们本身使用 LLVM 函数 llvm.round.f32
和 llvm.round.f64
实现。遗憾的是,documentation for llvm.round.*
没有说明如何控制舍入模式。 LLVM 参考资料中似乎也没有关于它的任何其他内容。我发现的其他函数甚至提到了舍入模式或者指定了 one 特定的舍入模式,或者说它是未定义的。
我找不到关于此的任何可靠信息。有 a post on the LLVM mailing list from 2011 that talks about x86-specific intrinsics, and a 2013 post to the Native Client issue tracker 似乎在谈论 假设的 内在特性以及如何难以移植。
盲目尝试:我会尝试编写一个小的 C 库来完成它,然后 link 就可以了。 LLVM 似乎不直接支持它。
恐怕我不了解 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[=的情况35=]53.
floor(2*x-y)
将给出所需的答案:2*x
是准确的,我们不必担心由于第 2 步而溢出。除了 [=] 之外的所有情况减法都是准确的19=],无论如何都会清楚地给出正确答案。
-
copysign
只是为了确保零的符号正确。如果你不被这些事情困扰,你可以把它关掉。
步骤 2 和 3 可以用一个简单的分支代替:
x-y < 0.5 ? y : y+1.0
但如果我没记错的话,避免此处的分支使代码对矢量化更加友好(这也是使用 ifelse
而不是 if
块的原因)。
我想将浮点数舍入到最接近的整数,当 "nearest integer" 并列时趋于正无穷大。
use std::num::Float;
fn main() {
assert_eq!(-0.0, (-0.5).round()); // fails!
}
然而,round
的文档说:
Round half-way cases away from 0.0.
我还没有看到任何可以让我改变舍入模式的东西,但总有一些方法,对吗?
看起来 Float::round
的实现,至少对于 f32
和 f64
,转发到 roundf32
/roundf64
内部函数,它们本身使用 LLVM 函数 llvm.round.f32
和 llvm.round.f64
实现。遗憾的是,documentation for llvm.round.*
没有说明如何控制舍入模式。 LLVM 参考资料中似乎也没有关于它的任何其他内容。我发现的其他函数甚至提到了舍入模式或者指定了 one 特定的舍入模式,或者说它是未定义的。
我找不到关于此的任何可靠信息。有 a post on the LLVM mailing list from 2011 that talks about x86-specific intrinsics, and a 2013 post to the Native Client issue tracker 似乎在谈论 假设的 内在特性以及如何难以移植。
盲目尝试:我会尝试编写一个小的 C 库来完成它,然后 link 就可以了。 LLVM 似乎不直接支持它。
恐怕我不了解 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[=的情况35=]53. floor(2*x-y)
将给出所需的答案:2*x
是准确的,我们不必担心由于第 2 步而溢出。除了 [=] 之外的所有情况减法都是准确的19=],无论如何都会清楚地给出正确答案。-
copysign
只是为了确保零的符号正确。如果你不被这些事情困扰,你可以把它关掉。
步骤 2 和 3 可以用一个简单的分支代替:
x-y < 0.5 ? y : y+1.0
但如果我没记错的话,避免此处的分支使代码对矢量化更加友好(这也是使用 ifelse
而不是 if
块的原因)。