나머지 연산자의 동작.
글쓴이: mmojz / 작성시간: 수, 2005/08/17 - 3:35오후
나머지 연산자를 쓰다가 음수를 생각하게 되었습니다.
예를 들어서 (-3) % 2 는 1 이 될 수도 있고 -1 이 될 수도 있는거 같습니다. 한번 궁금해서 여러 프로그램에 이 식을 넣고 답을 기다렸습니다.
먼저 MS 의 VC는 답을 -1 로 내놓았습니다.
윈도우즈 내장 계산기는 답을 -1 로 내놓았습니다.
하지만, MS Excel 은 답을 1 로 내놓았습니다...
뭐가 정답일까요?
셋다 MS 제품인데 말이죠. 글 올리기전에 검색 해봤으나 찾지 못하고 글 올립니다. (__)
Forums:
음수로 나오는데요? +_+엑셀에서 숫자표시 방식을 바꿔보세요.
음수로 나오는데요? +_+
엑셀에서 숫자표시 방식을 바꿔보세요.
Too Many Sceret is in your heart.
We must break it and don't forget it.
Until no more secret remains in your soul
Re: 나머지 연산자의 동작.
버전이 빠졌군요.
먼저 MS 의 MS VS 2003 은 답을 -1 로 내놓았습니다.
윈도우즈 엑스피 내장 계산기는 답을 -1 로 내놓았습니다.
하지만, MS Excel 2003 은 답을 1 로 내놓았습니다...
숫자표시방식은 어떻게 견들여야 하는건가요?; 다른 음수가 나올 만한 계산은 음수가 제대로 나옵니다만;
ps. marantz 님도 버전을 알려주세요.
파이썬 (2.4.1): 1루비 (1.8.2): 1펄 (5.8.6)
파이썬 (2.4.1): 1
루비 (1.8.2): 1
펄 (5.8.6): 1
Boo (?): -1
윈도우에서 테스트했습니다. 다른 언어의 테스트 결과도 보여주세요~
Re: 나머지 연산자의 동작.
나머지에 대해서 이야기를 하신다면 둘다 정답아닌가요?
나머지를 음수에 맞추던 양수에 맞추던.....
Ada같은 언어에서는 mod, rem이라는 두개의 연산자 함수가 있읍니다.
가물가물 하긴하지만 하나는 나누는 수의 부호에 하나는 나누어지는수의 부호에 나머지의 부호를 맞추는걸로 알고있읍니다.
MS에서 만든 프로그램 뿐만 아니라 언어 스펙이나 다른 프로그램들에서도
MS에서 만든 프로그램 뿐만 아니라 언어 스펙이나 다른 프로그램들에서도 정수 나눗셈과 나머지 연산자의 동작에 대한 정의는 천차만별입니다. 이건 사용하는 프로그램에 따라서 제각각이기 때문에 상황에 따라서 확인해 보고 사용하셔야 할 겁니다.
구체적으로, 대부분의 경우 a와 0이 아닌 b에 대해서 보통 다음 식이 성립합니다.
(a / b) * b + a % b == a
위의 식이 성립한다는 가정이 있을 경우, 정수 나눗셈을 할 때 어떻게 절삭하느냐(즉 인접한 정수 중 어느 걸 선택하느냐)는 크게 세 가지로 나뉩니다.
이렇게 하고 보니 소숫점 절삭 얘기가 되어 버렸군요. 아무튼 이런 정책은 언어마다 차이가 있습니다. (저는 정수 나눗셈에서 towards +infinity를 쓰는 걸 못 봤습니다. 실수 나눗셈의 경우 플래그 등등에 따라 제각기 다르지만...) 구체적으로, C의 경우 다음에서 볼 수 있듯이 0에 가깝게 절삭합니다.
C++에서는 구현체에 따라 다를 수 있다고 하면서 0에 가깝게 절삭하는 걸 권장하고 있습니다.
반면에 파이썬의 경우 다음과 같이 음의 무한대로 절삭합니다.
루비도 마찬가지입니다. (CVS의 ruby/numeric.c에서 가져 왔습니다. 이거 찾는 거 상당히 골때리는 짓이더군요-_-)
등등... 상황에 따라서 알아서 쓰시면 될 듯 합니다. 저는 개인적으로 음의 무한대로 절삭하는 걸 선호하긴 합니다. -_-;
만약 정책을 직접 정해야 할 경우 (즉 어떤 경우에라도 정해진 정책에 따라서 반올림되도록 하고 싶을 경우) 별도의 함수를 만들어서 쓰시면 되겠습니다. 어떤 경우든 a와 b가 모두 양수이면 별 문제가 없을 테니까 그걸 사용하면 되겠죠. 아래는 제가 대충 짜 본 C 코드이며 이상이 있을 수도 있습니다 -_-;;;
- 토끼군
덤: 몇 가지 예를 더 들어 보자면, php의 경우 나눗셈 연산자가 항상 실수를 반환하기 때문에-_- intval($a/$b) 처럼 써야 하는데 intval은 0에 가깝게 절삭합니다. VB도 해 봤는데 (정수 나눗셈 연산자 \가 따로 있음) 이것도 towards zero군요...
[/]C에서는 a/b + a%b = a 이어야만 합니다. 그런고로 -3 / 2
C에서는 a/b + a%b = a 이어야만 합니다. 그런고로 -3 / 2 = -1 이면 -3 % 2 = -1 이고 -3 / 2 = -2 이면 -3 % 2 = 1 입니다.
문제는 -3 / 2 의 결과값이 무엇인가 하는 것인데, / 연산자의 피연산자인 두 정수형 중에 하나라도 음수값이라면, 반올림의 방향은 구현체가 결정한다는군요.
위에 잘못썼군요.(a/b) + a%b = a위의 수식은 틀
위에 잘못썼군요.
(a/b) + a%b = a
위의 수식은 틀렸고, 아래 수식이 맞습니다.
(a/b)*b + a%b = a
답변 주신 분들 감사합니다.
일단 0에 가깝게 절삭한다고 하면 아래와 같이 동작하겠군요.
일단 자연수 a, b 에 대해 a%b 가 정의되었다고 하면
a%b 의 값은 |a|%|b| 이고, 부호는 a 의 부호를 따른다.
Re: 답변 주신 분들 감사합니다.
네 그렇게 동작하는 것 맞습니다. 사실 x86 프로세서 명령인 IDIV(signed divide) 명령도 그렇게 동작하지요.
- 토끼군
음.. 수학적으로 봤을때나머지의 정의는 "0 이상이고 나누는 수보다
음.. 수학적으로 봤을때
나머지의 정의는 "0 이상이고 나누는 수보다 작다"라고 알고 있습니다.
그러므로
(-3)%2 = -2 ... 1
라고 하는게 수학적 논리에 맞겠죠?
그런데
나누는 수가 음수면 어떻하죠?
나머지의 정의부터 모순이 생기는데.. (나누는 수는 항상 양수??? =_=a;; )
2005년 8월 17일.
[quote="어니스트"]음.. 수학적으로 봤을때나머지의 정의는 "0
처음부터 수학적으로는 (mod -3) 같은 표현 자체가 존재하지 않는 걸로 알고 있습니다. 단 배수 및 약수에서는 음수의 개념을 사용할 수 있습니다. 예를 들어서 12의 약수는 -12, -6, -4, -3, -2, -1, 1, 2, 3, 4, 6, 12입니다. (그래서 꼭 양의 약수라고 전제 조건을 달죠 보통;)
- 토끼군
흠
수학적으로 mod 가 없군요. 다른 사이트에서 본거 같은데 그냥 나머지를 간략하게 줄여서 mod 라고 했던거군요;;
Re: 흠
수학적으로 mod가 없다니요? :S 3 ≡ 11 (mod 4)라는 표현이 엄연히 존재합니다. (합동식)
- 토끼군
[quote="tokigun"][quote="어니스트"]음.. 수학적으로
(수학적으로) 항상 양수에 합동일 필요는 없습니다. 즉 mod 양수일 필요는 없습니다.
mod 양수가 mod 양수/음수보다 편리하기 때문에 일반적으로 그렇게 정의해서 사용하는 겁니다.
그리고 절대값도 반드시 작아야하지는 않지만 작은게 더 편리하기 때문에 보통 그렇게 합니다.
아! 그리고 "나머지"와 "합동"을 완전히 동일하게 취급할 수 없을 것 같습니다.
(정수론 책이 없어서 확인해볼 수가 없네요. :cry: )
[url]http://bbs.kldp.org/viewtopic.php?t
http://bbs.kldp.org/viewtopic.php?t=56663&start=0&postdays=0&postorder=asc&highlight=overflow 두번째 페이지에 참고할 만한 글이 있습니다.
[quote="kane"][quote="tokigun"][quote="어
아 생각해 보니까 합동식은 나머지랑 같은 게 아니죠. -_-;; mod 연산자를 4 mod 3 처럼 쓰는 경우도 봤는데 이 경우 나누는 수가 음수가 되는 경우가 가능한 지는 모르겠습니다. 그나저나 역시 제 기억이 틀린 것 같군요 OTL (언제나 틀려... 아윽)
그나저나...
kane 님께서 보여 주신 쓰레드에서 발췌해 왔는데, C99 스펙에서는 제가 위에서 인용한 바와 같이 무조건 truncation towards zero(즉 위에서 1과 2가 성립)로 되어 있더군요. "the result of the / operator is the algebraic quotient with any fractional part discarded."라면 소숫점 자리를 모조리 잘라 버린다는 거고 그러면 2번이 성립하게 되는 건데... 역시 C89와 C99의 차이가 아닐까 하고 추측해 봅니다. :S
- 토끼군
"The C Programming Language 2ed" 한글판 (IS
"The C Programming Language 2ed" 한글판 (ISBN 89-7163-026-4)을 보시면
38 페이지 첫문단에,
라고 나와있군요.
즉, C 프로그래밍을 하실때 "a%b"라는 식에서 a가 음수일 경우엔
기계마다 해석이 달라지므로 a가 양수인지 음수인지
확인하는 절차가 필요할 것 같습니다.
(그리고 사실 전, 아직까지 "음수a%b"를 해야하는 적이 없어서.. =_=a;; )
그리고 수학적으로 봤을때
"a mod b"라는 식에서
1) a<0 이며 b>0 일때
2) a>0 이며 b<0 일때
3) a<0 이며 b<0 일때
어떻게 정의가 되어있는지 궁금하군요.
토끼군님의 말씀대로 2)번은 존재하지 않는 표현인가요?
예전에 수학 관련 교양 시간에 교수님께서 저 문제에 대한 언급을 하셨던 것 같은데
책을 펴보니 이런.. 그시간에 졸았는지 필기가 중간에 끊겨있더군요.. OTL
제가 적어논건, "나머지는 0 이상이고 나누는 수 미만이다"라고 적혀있네요..
이것에 대해서 정확한 정의를 알 수 있을까요 ?
2005년 8월 17일.
a mod b에서 b가 음수라도 아무 문제가 없습니다.4 mod -3
a mod b에서 b가 음수라도 아무 문제가 없습니다.
4 mod -3은 ..., -5, -2, 1, 4, 7, ... 이고,
-4 mod -3은 ..., -7, -4, -1, 2, 5, ... 이죠.
이 중에서 보통 4 mod -3 = 1과 -4 mod -3 = 2를 취합니다.
하지만 4 mod 3 = 1에서 알수 있듯이 a는 c와 3과 -3, 즉 b와 -b에 대해서 합동이기 때문에 별 의미는 없죠.
그리고 "4 mod 3 = 1"과 "4 = 1 mod 3", "4 = 1 (mod 3)"이 모두 같은 의미입니다.
나머지에 대해 위키피디아에 관련 글이 있지만, 제가 뭔가 혼동하고 있는지 개운치가 않네요.
[quote="tokigun"]역시 C89와 C99의 차이가 아닐까 하고
외국에서도 나머지 가지고 말이 많았나 봅니다. ;)
[quote="ditto"]파이썬 (2.4.1): 1루비 (1.8.2
이런 복잡한 수학연산은 포트란입죠. (순 농담입니다.) :)
리눅스 박스에서 테스트 했습니다.
mod(-3,2)의 포트란 스런 답은:
gfortran -1
g95 -1
intel fortran -1
g77 -1
입니다. 위에 올라온 글들을 보면서 수에 대해 보다 흥미를 가집니다.(가질 것 같습니다.)
==========================
부양가족은 많은데, 시절은 왜 이리 꿀꿀할까요?
=====================
"지금하는 일을 꼭 완수하자."
[quote="kane"]나머지에 대해 위키피디아에 [url=http:/
나머지에 관해서는 링크하신 관련글의 (그 중에서도 일반적인 정수일 경우에 대한) 내용이 맞는 것 같습니다. 위키백과에 나와있듯이 일반적인 정수의 경우에는 두 개의 〈몫, 나머지〉 순서쌍이 존재합니다. 프로그래밍 언어에서 이 두 종류의 순서쌍 중 어느 것을 택하느냐는 언어 설계자의 생각에 따라 임의로 결정하면 그만이겠죠. (서로 다른 순서쌍에서 각각 몫과 나머지를 하나씩 가져오지만 않으면 됩니다. 즉, “몫 × 젯수 + 나머지 = 피젯수”라는 조건 만큼은 항상 만족시켜야 연산의 일관성을 유지할 수 있겠죠.)
Haskell의 경우, Integral 타입클래스에 속하는 모든 타입들(예를 들어 Int와 Integer 등)에 대해서 말 그대로 몫(quot)과 나머지(rem)를 구하는 함수들 외에 div와 mod도 따로 정의되어 있습니다. (이들이 항상 서로 다른 〈몫, 나머지〉 순서쌍을 계산한다는 의미는 아닙니다.)
위키 백과에서 Modular arithmetic과 Modulo operation도 참고하시면 도움이 될 것 같습니다.
--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!
댓글 달기