我需要对减法的结果进行平方运算,而且速度要快.

我已经确定了一些可能的方法,但我想听听利弊.

unsigned int a = 5;
unsigned int b = 7;


/* Approach 1a */
unsigned int c  = (a - b) * (a - b);

/* Approach 1b */
int d = (a - b);
unsigned int e = d * d;


/* Approach 2a */
unsigned int f = abs(a - b) * abs(a - b);

/* Approach 2b */
unsigned int g = abs((a - b) * (a - b));

/* Approach 2c */
unsigned int h = abs(a - b);
unsigned int i = h * h;


/* Approach 3a */
unsigned int j = (a > b) ? ((a - b) * (a - b)) : ((b - a) * (b - a))

我不确定如何确保随机负数不会被编译器优化,所以我只写了一般概念.我相信,仅仅通过观察就可以挑出一些(次)最优的解决方案.

推荐答案

考虑另一种 Select ,差额以unsigned而不是int的形式保存.

// Recommend avoiding
/* Approach 1b */
int d = (a - b);
unsigned int e = d * d;

/* Approach 1b_alt */
unsigned int d_alt = (a - b);
unsigned int e_alt = d_alt * d_alt;
  • 优点1:值为a - b > INT_MAX时,将差值保存为int会产生implementation defined behavior.典型的实现定义的行为按照OP的要求执行,但这并不能得到保证.

  • 优点2:当差值大于sqrt(INT_MAX),但不超过sqrt(UINT_MAX)时,等于使用int计算结果是int溢出和undefined behavior,但另存为unsigned不会导致溢出(即使超出范围也不会产生UB).int溢出的典型未定义行为按照OP的要求执行,但这并不能得到保证.应避免潜在的UB.


Given the modulo nature of unsigned math, /* Approach 1a */ and /* Approach 1b_alt */ are specified to produce the same result.
I recommend either of these approaches. They both perform as desired for all a, b where |a-b|^2 <= UINT_MAX.


OP asserts表示最终结果在unsigned范围内,因此结果为a, b的值对于优化并不重要.

C++相关问答推荐

exit(EXIT_FAILURE):Tcl C API类似功能

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

进程在写入管道时挂起

SSH会话出现意外状态

Boyer Moore算法的简单版本中的未定义行为

在C++中允许使用字符作为宏参数

当我用scanf(&Q;%S%S%S&Q;,单词0,单词1,单词2)输入多个单词时,除了最后一个单词外,每个单词的第一个字符都丢失了

C23标准是否向后兼容?

可以';t从A9G模块拨打电话

共享内存未授予父进程权限

我的代码可以与一个编译器一起使用,但不能与其他编译器一起使用

程序打印一些随机空行

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

使用替代日历打印日期

通过修改c中的合并排序对数组的偶数索引进行排序

是否可以在多字 C 类型中的任何位置混合存储和类型限定符?

GDB 用内容初始化数组

在 C/C++ 中原子按位与字节的最佳方法?

为什么 C 字符串并不总是等同于字符数组?

OpenGL 中的非渐变 colored颜色 变化