我最终最终自己回答了这个问题。对我来说,解决方案是用代码完成我以前在学校做的事情。该方法是这样的:
- 每次取号,并确保数字小数点右边的数字是相同的。因此,如果加入
2.1
和3.457
,则将第一个“正常化”为2.100
。记录小数点右边的位数,在本例中为三位。
- 现在删除小数点并使用
mpz_add
添加两个数字,现在变成2100
和3457
。结果是5557
。
- 最后,从右侧重新插入小数点三个字符(在这种情况下),给出正确答案
5.557
。
我在VBScript(下文)原型的溶液
function fadd(n1, n2)
dim s1, s2, max, mul, res
normalise3 n1, n2, s1, s2, max
s1 = replace(s1, ".", "")
s2 = replace(s2, ".", "")
mul = clng(s1) + clng(s2)
res = left(mul, len(mul) - max) & "." & mid(mul, len(mul) - max + 1)
fadd = res
end function
sub normalise3(byval n1, byval n2, byref s1, byref s2, byref numOfDigits)
dim a1, a2
dim max
if instr(n1, ".") = 0 then n1 = n1 & "."
if instr(n2, ".") = 0 then n2 = n2 & "."
a1 = split(n1, ".")
a2 = split(n2, ".")
max = len(a1(1))
if len(a2(1)) > max then max = len(a2(1))
s1 = a1(0) & "." & a1(1) & string(max - len(a1(1)), "0")
s2 = a2(0) & "." & a2(1) & string(max - len(a2(1)), "0")
numOfDigits = max
end sub
,最后在Visual C++(下文)。
#define Z(x) mpz_t x; mpz_init(x);
BSTR __stdcall FADD(BSTR p1, BSTR p2) {
USES_CONVERSION;
LPSTR sP1 = W2A(p1);
LPSTR sP2 = W2A(p2);
char LeftOf1[ 1024 ];
char RightOf1[ 1024 ];
char LeftOf2[ 1024 ];
char RightOf2[ 1024 ];
char * dotPos;
long numOfDigits;
int i;
int amtOfZeroes;
dotPos = strstr(sP1, ".");
if (dotPos == NULL) {
strcpy(LeftOf1, sP1);
*RightOf1 = '\0';
} else {
*dotPos = '\0';
strcpy(LeftOf1, sP1);
strcpy(RightOf1, (dotPos + 1));
}
dotPos = strstr(sP2, ".");
if (dotPos == NULL) {
strcpy(LeftOf2, sP2);
*RightOf2 = '\0';
} else {
*dotPos = '\0';
strcpy(LeftOf2, sP2);
strcpy(RightOf2, (dotPos + 1));
}
numOfDigits = strlen(RightOf1) > strlen(RightOf2) ? strlen(RightOf1) : strlen(RightOf2);
strcpy(sP1, LeftOf1);
strcat(sP1, RightOf1);
amtOfZeroes = numOfDigits - strlen(RightOf1);
for (i = 0; i < amtOfZeroes; i++) {
strcat(sP1, "0");
}
strcpy(sP2, LeftOf2);
strcat(sP2, RightOf2);
amtOfZeroes = numOfDigits - strlen(RightOf2);
for (i = 0; i < amtOfZeroes; i++) {
strcat(sP2, "0");
}
Z(n1);
Z(n2);
Z(res);
mpz_set_str(n1, sP1, 10);
mpz_set_str(n2, sP2, 10);
mpz_add(res, n1, n2);
char * buff = (char *) _alloca(mpz_sizeinbase(res, 10) + 2 + 1);
mpz_get_str(buff, 10, res);
char * here = buff + strlen(buff) - numOfDigits;
memmove(here + 1, here, strlen(buff)); // plus trailing null
*(here) = '.';
BSTR bResult = _com_util::ConvertStringToBSTR(buff);
return bResult;
}
我接受C是有点......好吧......不好意思,所以请随时批评它。所有有用的评论感激地收到。
我从这里继续实施FSUB和FMUL。 FDIV几乎没有那么令人满意,最终以三个版本并使用有理数。
最简单的就是使用mpq_t,对有理数的操作是确切的。 – 2013-01-09 15:18:34