مضيفا يطفو مع gmp يعطي "الصحيح" النتائج نوعا ما
-
05-07-2019 - |
سؤال
في البرمجية أدناه يمكنني استخدام mpf_add
إضافة إلى تمثيل سلسلة من اثنين العائمة القيم.ما أنا لا أفهم في هذه المرحلة هو السبب 2.2 + 3.2 = 5.39999999999999999999999999999999999999
.أنا أعتقد أن gmp
كان ذكيا بما يكفي لإعطاء 5.4
.
ما أنا فهم لا حول كيفية gmp هل العربات ؟
(راجع للشغل, عندما كتبت أول هذا لم أكن متأكد من كيفية إدراج العلامة العشرية ، وبالتالي زائد/ناقص رقم الاشياء في النهاية)
BSTR __stdcall FBIGSUM(BSTR p1, BSTR p2 ) {
USES_CONVERSION;
F(n1);
F(n2);
F(res);
LPSTR sNum1 = W2A( p1 );
LPSTR sNum2 = W2A( p2 );
mpf_set_str( n1, sNum1, 10 );
mpf_set_str( n2, sNum2, 10 );
mpf_add( res, n1, n2 );
char * buff = (char *) _alloca( 1024 );
char expBuffer[ 20 ];
mp_exp_t exp;
mpf_get_str(buff, &exp, 10, 0, res);
char * temp = ltoa( (long) exp, expBuffer, 10 );
if (exp >= 0) {
strcat(buff, "+" );
}
strcat(buff, expBuffer );
BSTR bResult = _com_util::ConvertStringToBSTR( buff );
return bResult;
}
المحلول
وهذا هو بسبب الخطأ الكامن في استخدام الحساب الفاصلة العائمة في بيئة الثنائية.
IEEE 754 معيارا لمزيد من المعلومات.
نصائح أخرى
ارن <لأ href = "https://stackoverflow.com/questions/178952/adding-floats- مع برنامج الرصد العالمي، يعطي-الصحيحة-النتائج النوع من قال # 178978 ">
قد يكون لديك نتائج أفضل إذا كنت تستخدم ثنائي ترميز عشري بدلا من أرقام النقطة العائمة، على الرغم من أنني لا يمكن حقا توجهك إلى أي مكتبات لذلك.
انتهى في نهاية المطاف الإجابة عن هذا بنفسي.الحل بالنسبة لي هو أن أفعل في رمز ماذا كنت أفعل في المدرسة.الأسلوب يعمل مثل هذا:
- تأخذ كل عدد و تأكد من أن عدد الأرقام إلى يمين الفاصلة العشرية هي نفسها.حتى إذا ما أضيف
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;
}
أنا أقبل أن ج قليلا ...حسنا ...المراوغة, لذا يرجى لا تتردد في نقد ذلك.جميع التعليقات المفيدة الترحاب.
ذهبت من هنا لتنفيذ FSUB و FMUL كذلك.FDIV لم يكن ما يقرب من ذلك مرضية تنتهي في ثلاثة إصدارات واستخدام الأعداد الكسرية.