gpt4 book ai didi

c++ - 从 Rust 和 C++ 设置 FPU 舍入方向没有任何改变

转载 作者:搜寻专家 更新时间:2023-10-31 01:35:49 26 4
gpt4 key购买 nike

据我所知,将舍入方向设置为 +Inf 会在计算 1/3 时产生 0.333334,而在设置为 0.33333 时会产生 0.33333 -Inf.

当我尝试在 C++ 中使用 fesetround(0x400)fesetround(0x800) 时,情况并非如此。我在 Rust 中使用 FFI 从 C 调用 fsetround 得到相同的行为。

C++代码:

#include <cfenv>
#include <iostream>
#include <iomanip>

using namespace std;

int main() {
double ratio = (double)1/(double)10;
fesetround(FE_UPWARD);
cout << fegetround() << " upward " << setprecision(18) << ratio << std::endl;
fesetround(FE_DOWNWARD);
cout << fegetround() << " downward " << setprecision(18) << ratio << std::endl;
return 0;
}

( Pastebin )

防 rust 代码:

extern crate libc;

use libc::c_int;

#[link(name = "rounding")]
extern {
pub static fe_upward: c_int;
pub static fe_downward: c_int;
fn fesetround(rount: c_int) -> c_int;
fn fegetround() -> c_int;
}

pub fn upward_round() -> i64 {
unsafe {
fesetround(fe_upward);
fegetround() as i64
}
}

pub fn downward_round() -> i64 {
unsafe {
fesetround(fe_downward);
fegetround() as i64
}
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_upward() {
unsafe {
assert_eq!(fe_upward as i64, upward_round());
}
}
#[test]
fn test_downward() {
unsafe {
assert_eq!(fe_downward as i64, downward_round());
}
}
}

( Pastebin )

最佳答案

Starblue 的评论是正确的,但让我扩展一下。

“四舍五入”是指在某些未指定的基数中通过一组有限的数字来近似实数。您的示例 1/3 = 0.333333 假设四舍五入为 6 个十进制 数字,即基数 10。

但是,计算机以 2 为基数工作。二进制 1/11 是 .1010101010101... 如您所见,四舍五入有点奇怪。如果舍入到最接近 6 位,则为 .101011,如果舍入为 7 位,则为 .1010100 - 最后一位始终与倒数第二位相同位,那是因为位交替。

当然,向上舍入和向下舍入更简单。舍入 .10101010... 只是将结果截断为 N 位:0.101010。向上舍入只是将最后一位加 1。

现在您以二进制进行四舍五入,但以十进制打印结果。这意味着这些模式根本不明显。

这就是事情变得复杂的地方”:在 FP 函数中几乎所有地方都需要舍入,因此它应该很快。这意味着您需要编译舍入模式。但是您不能在每次调用 fesetround。这意味着需要妥协,妥协是 #pragma STDC FENV_ACCESS。如果它是 ON,您将获得慢速代码并且 fesetround 可以正常工作。如果关闭(默认),fesetround 会产生未指定的结果。

关于c++ - 从 Rust 和 C++ 设置 FPU 舍入方向没有任何改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36681157/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com