相关疑难解决方法(0)

在 32 位机器上,当我不将其结果存储在变量中时,atan2 是不确定的。为什么?

考虑这段 C 代码:

#include <math.h>
#include <stdbool.h>
#include <stdio.h>

bool foo(int a, int b, int c, int d) {
    double P = atan2(a, b);
    double Q = atan2(c, d);
    return P < Q;
}

bool bar(int a, int b, int c, int d) {
    return atan2(a, b) < atan2(c, d);
}

int main() {
    if (foo(2, 1, 2, 1)) puts("true"); else puts("false");
    if (bar(2, 1, 2, 1)) puts("true"); else puts("false");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我用 编译它时gcc -lm -m64,它会打印

false …
Run Code Online (Sandbox Code Playgroud)

c c++ floating-point 32-bit ieee-754

15
推荐指数
0
解决办法
208
查看次数

如果数学移至内联函数,为什么 C++ 舍入行为(对于编译时常量)会发生变化?

考虑以下函数:

static inline float Eps(const float x) {
  const float eps = std::numeric_limits<float>::epsilon();
  return (1.0f + eps) * x - x;
}

float Eps1() {
  return Eps(0xFFFFFFp-24f);
}

float Eps2() {
  const float eps = std::numeric_limits<float>::epsilon();
  const float x = 0xFFFFFFp-24f;
  return (1.0f + eps) * x - x;
}
Run Code Online (Sandbox Code Playgroud)

-O2with中-std=c++20,这两个函数都编译为一个函数,movss后跟一个ret针对 x86 的 using clang 16.0.0 和mov一个bx针对 ARM 的 with gcc 11.2.1。为 ARM 生成的程序集与返回值 ~5.96e-8 一致,但为 x86 生成的程序集则不然。 …

c++ floating-point clang compiler-optimization clang++

7
推荐指数
1
解决办法
257
查看次数

gcc -ffp-contract选项的差异

我对-ffp-contractGNU GCC中的标志有疑问(请参阅https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)。

标志文档编写如下:

-ffp-contract=off禁用浮点表达式收缩。-ffp-contract=fast如果目标对它们有本机支持,则启用浮点表达式收缩,例如形成融合的乘法加法运算。-ffp-contract=on如果语言标准允许,则启用浮点表达式收缩。目前尚未实现,并且将其视为-ffp-contract=off。默认值为-ffp-contract=fast

现在的问题是:

  • fast和on和有什么不一样?
  • 在FMA之外是否还有其他收缩示例(或类似的融合乳胶子)?

c floating-point gcc compiler-optimization fma

5
推荐指数
1
解决办法
1102
查看次数

浮点缩写是否只允许在一个表达式中使用?

这个 C/C++ 简化测试用例:

int x = ~~~;
const double s = 1.0 / x;
const double r = 1.0 - x * s;

assert(r >= 0); // fail
Run Code Online (Sandbox Code Playgroud)

数值不稳定,并且符合断言。原因是最后的计算可以用FMA来完成,这就带来了r负面影响。

Clang 默认启用了 FMA(从版本 14 开始),因此它导致了一些有趣的回归。这是一个运行版本:https://godbolt.org/z/avvnnKo5E


有趣的是,如果将最后一个计算一分为二,则不会发出 FMA 并且结果始终为非负:

int x = ~~~;
const double s = 1.0 / x;
const double tmp = x * s;
const double r = 1.0 - tmp;

assert(r >= 0); // OK
Run Code Online (Sandbox Code Playgroud)

这是 IEEE754 / FP_CONTRACT 的保证行为,还是这是在玩火,应该找到一种数值更稳定的方法?我找不到任何迹象表明 fp 收缩仅意味着“本地”发生(在一个 …

c++ floating-point precision

2
推荐指数
1
解决办法
161
查看次数