" x = -x"之间是否存在功能差异?和" x * = -1"否定价值观?

时间:2015-05-27 13:12:13

标签: c++ c multiplication negative-number

代码示例:

float f = 123.456;
int i = 12345;
// negate by changing sign
i = -i;
f = -f;
// negate by multiplying with -1
i *= -1;
f *= -1.0f;

除了美学之外,是否有任何理由为什么人们应该选择一种方式而不是另一种呢?

对我而言,乘法似乎有点不必要。但我更经常地看到乘法风格,并希望听到除了偏好之外是否有充分的理由。

2 个答案:

答案 0 :(得分:6)

根据我对“fastest-way-to-negate-a-number

的回答

速度

similar question的答案表明:

  • 你应该忘记速度并选择你认为最具可读性的成语。
  • 几乎所有编译器都为a = -aa *= -1等等生成等效的最佳代码(可能是单个指令)。
    • 但是虽然MSVS 2012(优化?)每个都使用一条指令,但= -a需要1个周期,*= -1需要3个。
  • 任何使其速度更快的尝试都会降低其可读性,并且很容易使其变慢。
  • 如果您需要优化,则应首先分析生成的代码和性能。

副作用和不稳定

*= -1成语有一个实际的好处:你只需要写一次左手边,它只被评估一次。当LHS长,复杂或昂贵或可能有副作用时,这是相关的:

(valid ? a : b)[prime_after(i++)] *= -1;
*look_up (input) *= -1;  // Where look_up may have side-effects
parity[state][(unsigned int)getc(stdin)] *= -1;
variable_with_a_long_explanatory_name *= -1;

这种不可靠性的另一个优点是,在寻找错误时,可以确定该数字确实被 in situ 否定,并且这两个表达式之间没有细微差别。

一旦采用了成语,人们就会在其他情况下坚持使用,所以坚持*= -1是可以理解的。

答案 1 :(得分:1)

建议使用最能解释代码的内容,除非使用旧平台或编译器。在这种情况下,使用否定。

以下是一些不起眼的差异:

带有非2补码的

int格式:
在以前的日子里,乘以0-1可能会导致0,但0的否定可能会导致-0。当然,0-0具有相同的,但标志不同。并非所有非2的补充机器都有相同的工作原理。

浮点:
速度:智能编译器将为f *= -1.0ff *= -f创建高效且可能相同的代码。然而,较小的编译器可能无法识别这种等效性并且执行速度比另一种慢。

舍入:否定不需要调用任何舍入,但乘法,即使是1.0,也可能涉及一轮。这种情况发生在两种情况下:当变量具有更高的精度(在现代C中允许,FLT_EVAL_METHOD)和在使用base-16而不是base-2执行FP的机器(更像是文件)时。在后一种情况下,精确摆动(例如IBM Floating Point)和简单的乘法将呈现圆形乘积。这种情况下,这种行为并不常见。

还存在FP格式,其具有针对相同值的多个表示,但是乘以1将返回优选格式,而否定将简单地翻转符号位。结果与相同,但FP编号的位模式不同。