펄의 버그?

Munsen의 이미지

대부분의 프로그래밍 언어에는 % 연산자가 있습니다. 나눗셈의 나머지를 구하는 연산자죠.

얼마전에 Perl로 Xchat용 계산기를 만들었습니다. 그러다가.. 지인이 테스트해준다더군요.

그러다보니 Perl의 % 연산이 C의 그것과 다르다는 걸 알아냈습니다.(수학적으로봐도 틀립니다.)

저는 수학을 못합니다. 그래서 지인이 알려주길.

"정석을 보면 너무 오래전에 봐서 기억은 가물가물하지만.
정수 a를 정수 b로 나눈 몫을 q 나머지를 r 이라고 하면
a=bq+r이라고 한다 (0 =< r < b)"

#!/usr/bin/perl
 
print 3 % -7 . "\n";   # 3 % -7을 출력

위의 코드에서는 -4를 출력합니다.

#include <stdio.h>
 
int main(void)
{
    int a = 3;
    int b = -7;
 
    printf("%d %% %d = %d\n", a, b, a % b);
    return 0;
}

이 코드에서는 3을 출력합니다.

여담으로 bc께서는 3이라고 합니다.

gamdora의 이미지

vacancy의 이미지

a = bq + r
.. 에서 r의 범위를 저렇게 얘기하는 게 일반적인 건
a와 b가 음이 아닌 정수일 때고요.
( 사실 r의 범위를 저렇게 잡는 건 다른 문제 풀 때 쓰는 '가정'이죠. )

그 외의 경우,
a와 b가 주어졌을 때 나오는 (q, r)의 쌍이
a = bq + r 로만 나오면 버그라고 보기 어렵습니다.

예를 들어,
a = 7, b = -3 일 때,
(a/b, a%b) = (-2, 1), (-3, -2) 는 보통 옳은 구현으로 보지만,
(a/b, a%b) = (-2, -2), (-3, 1) 는 보통 틀린 구현으로 보죠.

역시
a = -7, b = -3 일 때,
(a/b, a%b) = (2, -1), (3, 2) 는 보통 옳은 구현으로 보지만,
(a/b, a%b) = (3, -1), (2, 2) 는 보통 틀린 구현으로 봅니다.

Munsen의 이미지

그렇군요.

Quote:
( 사실 r의 범위를 저렇게 잡는 건 다른 문제 풀 때 쓰는 '가정'이죠. )

이건 가정이 아니라 공리인듯합니다.

http://en.wikipedia.org/wiki/Modulo_operation

수학에서는 양수인게 일반적인 것 같습니다. 물론 음수로 해도 틀린건 아니라고 하네요.(-_-;)

netionics의 이미지

양수 나누기 양수는 결과가 딱 하나지만
부호가 둘다 음수이거나 한 쪽이 음수라면 2가지 결과를 생각해 볼 수 있습니다.

3 / -7 의 몫을 0으로 보면 나머지가 3이 나올테고 (-7 * 0 + 3 = 3)
-1로 보면 나머지가 -4가 나옵니다 (-7 * -1 - 4 = 3)
나머지가 양수로 나오느냐 음수로 나오느냐는 언어마다 다릅니다.

c는 나머지의 부호를 피제수(3)와 같게 하고
Perl은 제수(-7)와 같게 하기 때문에 다른 결과가 나오는 것입니다.

:)

redneval의 이미지

저는 수학적인 내용은 모르겠습니다만,

공식문서에도 나와있듯이, 이는 펄의 `특징'입니다. (`버그'가 아니고..)

출처 : http://perldoc.perl.org/perlop.html#Multiplicative-Operators

Quote:

Binary "%" computes the modulus of two numbers. Given integer operands $a and $b : If $b is positive, then $a % $b is $a minus the largest multiple of $b that is not greater than $a . If $b is negative, then $a % $b is $a minus the smallest multiple of $b that is not less than $a (i.e. the result will be less than or equal to zero). Note that when use integer is in scope, "%" gives you direct access to the modulus operator as implemented by your C compiler. This operator is not as well defined for negative operands, but it will execute faster.

"%" 연산자는 두 숫자의 나머지 연산을 수행한다. $a 와 $b 가 인자일 때를 보면, $b 가 양수이면, $a%$b 는 "$a - [$a보다 크지않은 가장 큰 $b의 배수]" 값을 갖는다. $b 가 음수이면, $a%$b 는 "$a - [$a보다 작지않은 가장 작은 $b의 배수]"값을 갖는다. (즉, 결과값이 0 또는 음수 값이 된다.) 한 가지 첨언하면, "use integer;" 를 사용하면 C 컴파일러와 같은 결과를 얻을 수 있다. 이 경우에는 $b가 음수인 경우에 잘 정의되지 않은 문제점이 있지만, 그러나 원래의 %연산자보다는 더 빠르게 실행된다.

--------------------Signature--------------------
Light a candle before cursing the darkness.

7339989b62a014c4ce6e31b3540bc7b5f06455024f22753f6235c935e8e5의 이미지

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.