代码示例:
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;
除了美学之外,是否有任何理由为什么人们应该选择一种方式而不是另一种呢?
对我而言,乘法似乎有点不必要。但我更经常地看到乘法风格,并希望听到除了偏好之外是否有充分的理由。
答案 0 :(得分:6)
根据我对“fastest-way-to-negate-a-number”
的回答similar question的答案表明:
a = -a
,a *= -1
等等生成等效的最佳代码(可能是单个指令)。
= -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.0f
和f *= -f
创建高效且可能相同的代码。然而,较小的编译器可能无法识别这种等效性并且执行速度比另一种慢。
舍入:否定不需要调用任何舍入,但乘法,即使是1.0,也可能涉及一轮。这种情况发生在两种情况下:当变量具有更高的精度(在现代C中允许,FLT_EVAL_METHOD
)和在使用base-16而不是base-2执行FP的机器(更像是文件)时。在后一种情况下,精确摆动(例如IBM Floating Point)和简单的乘法将呈现圆形乘积。这种情况下,这种行为并不常见。
还存在FP格式,其具有针对相同值的多个表示,但是乘以1将返回优选格式,而否定将简单地翻转符号位。结果与值相同,但FP编号的位模式不同。