$ perl -e 'print 2**0.5**2'
1.18920711500272
perl 에서 이런 계산식 결과 값을 출력해봤는데 결과가 예상과 다르게 나와서 버그를 발견한 건 아닌가 생각했다. 2의 0.5 승, 즉 sqrt(2)에 다시 2승을 하면 2가 나와야 할 것 같은데 다른 값이 나왔다. perl 버전이 오래된 것이라서 그런가해서 여러 버전의 perl로도 해봤다. 결론부터 말하자면 버그는 아니다. print 사용법과 ** 연산자의 associativity 때문에 발생하는 것이다. +, - 등의 연산자는 left associativity를 가지지만 ** 연산자는 right associativity를 가진다. 그러면 왼쪽 먼저 계산이 되도록 괄호를 쓰면 되는데 그래도 결과가 원하는대로 안나온다. use warnings을 추가해보면 구체적인 이유를 알 수 있다.
$ perl -e 'use warnings; print (2**0.5)**2'
print (...) interpreted as function at -e line 1.
Useless use of exponentiation (**) in void context at -e line 1.
1.4142135623731
print 가 함수로 처리되어서 print(2**0.5) 가 먼저 처리되고 그 결과(void)에 대하여 **2를 하려고 하니 원하는대로 나오지 않는다. warning 메시지가 하나 나오긴 하지만..
$ perl -e 'use warnings; print ((2**0.5)**2)'
print (...) interpreted as function at -e line 1.
2
전체를 감싸는 괄호를 하나 더 추가하니 원하는 결과가 나왔다.
언어 특성상 어쩔 수 없기는 하지만 자칫 실수하기 쉬운 특징인 것 같다. 가능한 print 문 내에 계산식을 쓰지 않고 먼저 계산 값을 변수에 저장해서 그 변수를 출력하도록 하는 것이 좋겠다. 그리고 use warnings를 함께 쓰는 것도 예방하기 좋을 것 같다.(다만 use warnings를 쓰면 실행은 정상적으로 되어도 불필요하게 메시지 출력이 과도해서 출력 메시지를 저장하면 disk full 등의 문제가 발생할 수 있다.)
$ perl -e 'use warnings; $r=(2**0.5)**2; print $r'
2
댓글 없음:
댓글 쓰기