سؤال

في البرمجية أدناه يمكنني استخدام 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 ">

قد يكون لديك نتائج أفضل إذا كنت تستخدم ثنائي ترميز عشري بدلا من أرقام النقطة العائمة، على الرغم من أنني لا يمكن حقا توجهك إلى أي مكتبات لذلك.

انتهى في نهاية المطاف الإجابة عن هذا بنفسي.الحل بالنسبة لي هو أن أفعل في رمز ماذا كنت أفعل في المدرسة.الأسلوب يعمل مثل هذا:

  1. تأخذ كل عدد و تأكد من أن عدد الأرقام إلى يمين الفاصلة العشرية هي نفسها.حتى إذا ما أضيف 2.1 و 3.457, 'تطبيع' أول واحد 2.100.الاحتفاظ بسجل من عدد من الأرقام على يمين الفاصلة العشرية في هذه الحالة ثلاثة.
  2. الآن إزالة العلامة العشرية و استخدام mpz_add لإضافة اثنين من الأرقام ، التي أصبحت الآن 2100 و 3457.والنتيجة هي 5557.
  3. أخيرا, أعد العشرية ثلاثة أحرف (في هذه الحالة) من الحق ، وإعطاء الإجابة الصحيحة من 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 لم يكن ما يقرب من ذلك مرضية تنتهي في ثلاثة إصدارات واستخدام الأعداد الكسرية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top