首页 > 改变固有思维的计算题

改变固有思维的计算题

下面是一道常见的计算题目,最初刚看时,觉得是一个简单的计算题,应该是我学艺不精,得到的结果与在console上得到的不一样。

var a = 3, b = 5;
a = ( a - ( b = ( a = a + b ) - b ) );
>> 0

大家感兴趣的可以看看,解释下


這道題遠沒有看上去那麼簡單,實際上與直譯器的原理有關。

有人說上面那道口算也能算對,那麼看現在這道題:

var a = 3, b = 5;
a = a - ( b = a = a + b ) - b;

答案嘛,自己運行去看啦。


Some Gotchas in Arithmetic Expression Evaluation : JavaScript


对于不同Computer language,对运算符的处理方案不同,计算结果也有所不同。
如题目:
var a = 3, b = 5;
a = ( a - ( b = ( a = a + b ) - b ) );

C语言下运行结果:a=5, b=3.
Java下运行结果:a=0, b=3.
javascript下运行结果:a=0,b=3.
//-----------------------
注:其他语言还没进行测试


a = 3 - ( b = ( a = 3 + 5 ) - 5 ) = 0

把二元運算符看作一個函數,函數的參數從左到右進棧。右邊改變的不會影響左邊已進棧的。

使用逆波蘭表示法就明顯了

a = 3; b = 5; 

a = ( a - ( b = ( a = a + b ) - b ) );

a 3 b a 3 5 + = 5 - = - =

a 3 b a 8 = 5 - = - =

a 3 b 8 5 - = - =

a 3 b 3 = - =

a 3 3 - =

a 0 =

0

话说这道题有啥特别的?口算了一下就是0啊


楼主的问题可以总结为“子表达式的副作用如果改变表达式其他变量,会发生什么事情?”实际上除了赋值语句以外,子表达式包含++和--、函数调用也可以达到类似效果。另外,函数调用时,一个参数的表达式也可能影响到另一个参数。

问题的答案依赖于参数的求值顺序。有些语言是不在标准中规定求值顺序,因此规范给出的答案是undefined behavior,具体的答案依赖于编译器或解释器,如C++ 11前的C++。至于JavaScript,是严格从左到右求值的(有括号则优先求子表达式的值),因此,只要注意运算符的优先级,并在遇到赋值号时修改变量的值,就得到答案。


var a = 3, b = 5;
a = a - ( b = a = a + b ) - b;

-13=3-(3-3+5)-5


你既然都把它当成数学问题来对待了,那就用数学的方法去解就行了吧。( a - ( b = ( a = a + b ) - b ) ) 这个等式是个简单的四则运算,去掉其中的等号,结果就一目了然,( a - ( ( a + b ) - b ) ),这不就解完了。即使交给计算机,他也不能违背数学的规则。


从左往右,都是加减,如果括号没匹配,就先计算加减,完了括号匹配,就赋值,依次计算就是0.

【热门文章】
【热门文章】