유효 자릿수를 초과하는 곱셈 구현
작성자: ameya 님실행 횟수: 569
※ 이 라이브러리는 회원이 작성한 작품입니다. 본 사이트는 그 내용에 대해 관여하지 않습니다.
여기서는 곱셈 결과를 두 개의 변수에 저장하여 자릿수를 두 배로 확보하는 한 가지 방법을 보여줍니다. 설명을 위해 10자리로 설정했지만, 50자리라도 같은 원리로 처리할 수 있습니다.
소스 코드는 다음과 같습니다.
보기 불편하므로 print 문은 생략했습니다.
/* keta는 자릿수를 나타내는 예약어입니다 */
ketahalf = keta / 2; /* ← 자릿수의 절반으로 나눈 값 */
mxall = 10 ^ keta; /* ← 상위 자릿수를 표시할 때 지수 표기를 */
mxhalf = 10 ^ ketahalf; /* ← 이를 피하기 위해 이 값들로 나누고 있습니다. */
/* 입력값은 A와 B이며, 각각 ah, a와 bh, b로 나눕니다 */
ah = rounddown(A, -ketahalf);
bh = rounddown(B, -ketahalf);
a = A - ah;
b = B - bh;
/* 반으로 나누는 것은 곱셈을 통해 유효숫자를 자릿수 내에 맞추기 위함입니다 */
/* 상위 자리끼리, 하위 자리끼리의 곱셈 */
cch = ah * bh;
cc = a * b;
/* 대각선 곱셈 */
m1 = ah * b;
m2 = bh * a;
/* 대각선 곱셈 결과를 각각 분할 */
mh1 = rounddown(m1, -keta);
m1 = m1 - mh1;
mh2 = rounddown(m2, -keta);
m2 = m2 - mh2;
/* 대각선 곱셈 결과들의 덧셈 */
th = mh1 + mh2;
/* 여기서 하위 자리의 덧셈은 진위가 발생할 가능성이 있으므로 특정 기법을 사용하고 있습니다 */
tt = (m1 - 5E+9) + (m2 - 5E+9);
if (tt < 0) {
tt = tt + 1E+10;
} else {
th = th + 1E+10;
}
/* 처음에 상위와 하위 각각의 곱셈 결과를 더합니다 */
cch = cch + th;
/* 여기에서도 하위로 진위가 발생할 가능성이 있습니다 */
cc = (cc - 5E+9) + (tt - 5E+9);
if (cc < 0) {
cc = cc + 1E+10;
} else {
cch = cch + 1E+10;
}
/* 답을 표시합니다. */
println(-11, cch / mxall, cc);
/* 이해하기 꽤 어려울 수 있겠지만,
여기까지 여러 가지 작업을 하는 것은 어디까지나 ‘유효숫자 보존’을 위한 것
이라는 점에 주목하면 여러 가지가 보이기 시작할 것입니다. */
보기 불편하므로 print 문은 생략했습니다.
/* keta는 자릿수를 나타내는 예약어입니다 */
ketahalf = keta / 2; /* ← 자릿수의 절반으로 나눈 값 */
mxall = 10 ^ keta; /* ← 상위 자릿수를 표시할 때 지수 표기를 */
mxhalf = 10 ^ ketahalf; /* ← 이를 피하기 위해 이 값들로 나누고 있습니다. */
/* 입력값은 A와 B이며, 각각 ah, a와 bh, b로 나눕니다 */
ah = rounddown(A, -ketahalf);
bh = rounddown(B, -ketahalf);
a = A - ah;
b = B - bh;
/* 반으로 나누는 것은 곱셈을 통해 유효숫자를 자릿수 내에 맞추기 위함입니다 */
/* 상위 자리끼리, 하위 자리끼리의 곱셈 */
cch = ah * bh;
cc = a * b;
/* 대각선 곱셈 */
m1 = ah * b;
m2 = bh * a;
/* 대각선 곱셈 결과를 각각 분할 */
mh1 = rounddown(m1, -keta);
m1 = m1 - mh1;
mh2 = rounddown(m2, -keta);
m2 = m2 - mh2;
/* 대각선 곱셈 결과들의 덧셈 */
th = mh1 + mh2;
/* 여기서 하위 자리의 덧셈은 진위가 발생할 가능성이 있으므로 특정 기법을 사용하고 있습니다 */
tt = (m1 - 5E+9) + (m2 - 5E+9);
if (tt < 0) {
tt = tt + 1E+10;
} else {
th = th + 1E+10;
}
/* 처음에 상위와 하위 각각의 곱셈 결과를 더합니다 */
cch = cch + th;
/* 여기에서도 하위로 진위가 발생할 가능성이 있습니다 */
cc = (cc - 5E+9) + (tt - 5E+9);
if (cc < 0) {
cc = cc + 1E+10;
} else {
cch = cch + 1E+10;
}
/* 답을 표시합니다. */
println(-11, cch / mxall, cc);
/* 이해하기 꽤 어려울 수 있겠지만,
여기까지 여러 가지 작업을 하는 것은 어디까지나 ‘유효숫자 보존’을 위한 것
이라는 점에 주목하면 여러 가지가 보이기 시작할 것입니다. */
이 계산에 대한 고객 피드백이 아직 없습니다.
정수를 고려할 때, 숫자가 유효 자릿수로 반올림되어 버리는 것은 문제죠.
본래 곱셈의 답을 정확하게 구하려면 두 배의 유효 자릿수가 필요합니다.