为什么添加圆括号会更改此Scala表达式的结果?
我正在将一些C代码移植到Scala,Scala广泛使用浮点算法。基于C版本的复制/粘贴,我在Scala中编写了以下代码:为什么添加圆括号会更改此Scala表达式的结果?,scala,Scala,我正在将一些C代码移植到Scala,Scala广泛使用浮点算法。基于C版本的复制/粘贴,我在Scala中编写了以下代码: val complimentaryTerms = 2640.96e-6 * sin (f5) + 63.52e-6 * sin (2.0 * f5) + 11.75e-6 * sin (2.0 * f3 - 2.0 * f4 + 3.0 * f5) + 11.21e-6 * sin (2.0 * f3 - 2.
val complimentaryTerms = 2640.96e-6 * sin (f5)
+ 63.52e-6 * sin (2.0 * f5)
+ 11.75e-6 * sin (2.0 * f3 - 2.0 * f4 + 3.0 * f5)
+ 11.21e-6 * sin (2.0 * f3 - 2.0 * f4 + f5)
- 4.55e-6 * sin (2.0 * f3 - 2.0 * f4 + 2.0 * f5)
+ 2.02e-6 * sin (2.0 * f3 + 3.0 * f5)
+ 1.98e-6 * sin (2.0 * f3 + f5)
- 1.72e-6 * sin (3.0 * f5)
- 0.87e-6 * t * sin (f5)
此计算的结果与C版本产生的结果略有出入。但是,如果我将表达式括在括号中,如下所示:
val complimentaryTerms = (2640.96e-6 * sin (f5)
+ 63.52e-6 * sin (2.0 * f5)
+ 11.75e-6 * sin (2.0 * f3 - 2.0 * f4 + 3.0 * f5)
+ 11.21e-6 * sin (2.0 * f3 - 2.0 * f4 + f5)
- 4.55e-6 * sin (2.0 * f3 - 2.0 * f4 + 2.0 * f5)
+ 2.02e-6 * sin (2.0 * f3 + 3.0 * f5)
+ 1.98e-6 * sin (2.0 * f3 + f5)
- 1.72e-6 * sin (3.0 * f5)
- 0.87e-6 * t * sin (f5))
结果值与C版本完全匹配。似乎有圆括号和没有圆括号时的操作顺序一定不同,但我不明白为什么会有什么不同。知道这里发生了什么吗?这是因为分号推理。示例(
/;
-推断分号):
加括号:
val x = (1
+ 1) //;
println(x) // 2
或带有尾随“+”:
分号推理规则除非满足以下条件之一,否则行尾将被视为分号:
奇怪的虫子?你为什么不试着逐步简化这个表达式,直到你得到一个最简单的表达式,给出一个差异?例如
2640.96e-6*sin(f5)+63.52e-6*sin(2.0*f5)
是否给出了差异?如果你去掉第一项的系数会怎么样?(你也可以试着看发射的字节码。它不像听起来那么可怕。它不像看x86汇编程序(尽管承认它并不遥远)。但是,请先尝试获取一个简单的表达式,因此字节码相对较短。我怀疑这与推断的恭维术语类型有关。(嗯,您也可以尝试println恭维术语。getClass()
,然后查看是否相同。尝试将+和-移动到前一行,使它们位于行的末尾而不是开头。发现得很好。规则听起来很合理。但是……这个错误完全不明显。我想,当您第二次遇到这个错误时,它会变得很明显?它也不会出错,因为e有一元数
和一元数
方法,即+1.1
是一个有效的表达式,但是(例如)*1.1
不是。是的,我忘了提到它。这是一个相当大的问题。我很惊讶我以前没有听说过它。我似乎记得在奥德斯基的书中简要提到过这个问题,但显然没有留下印象。
val x = (1
+ 1) //;
println(x) // 2
val x = 1 +
1 //;
println(x) // 2