5

実数が double で正確に表現できる場合に true を返す C++ 関数を作成するにはどうすればよいですか?

bool isRepresentable( const char* realNumber )
{
   bool answer = false;
   // what goes here?
   return answer;
}

簡単なテスト:

assert( true==isRepresentable( "0.5" ) );
assert( false==isRepresentable( "0.1" ) );
4

6 に答える 6

5

数値を a + N / (10^k) の形式に解析します。ここで、a と N は整数で、k は小数点以下の桁数です。

例: 12.0345 -> 12 + 345 / 10^4、a = 12、N = 345、k = 4

さて、10^k = (2 * 5) ^ k = 2^k * 5^k

分母の 5^k 項を取り除く場合にのみ、数値を正確な 2 進分数として表すことができます。

結果は (N mod 5^k) == 0 をチェックします

于 2008-11-04T18:18:53.157 に答える
5

聖なる宿題、バットマン!:)

これが興味深いのは、単純に (atof|strtod|sscanf) -> sprintf ループを実行して、元の文字列が返されたかどうかを確認できないことです。多くのプラットフォームの sprintf は、「0.1 にできるだけ近い」double を検出し、たとえば、0.1 は正確に表現できない場合でも、0.1 として出力します。

#include <stdio.h>

int main() {
    printf("%llx = %f\n",0.1,0.1);
}

プリント: 3fb999999999999a = 0.100000

私のシステムで。

本当の答えは、おそらく double を解析して正確な分数表現 (0.1 = 1/10) に変換し、atof 変換時間分母が分子に等しいことを確認する必要があります。

おもう。

于 2008-11-04T16:17:42.263 に答える
1

これが私のバージョンです。sprintf は 0.5 を 0.50000 に変換します。末尾のゼロを削除する必要があります。

編集: 0 で終わる小数点のない数字を正しく処理するように書き直す必要があります (12300 など)。

bool isRepresentable( const char* realNumber )
{
   ブール回答 = false;

   double dVar = atof(実数);
   文字チェック[20];
   sprintf(check, "%f", dVar);

   // 末尾のゼロを削除する - TODO: 文字列の小数点の場合のみ行う
   for (int i = strlen(check) - 1; i >= 0; i--) {
     if (check[i] != '0') ブレーク;
     チェック[私] = 0;
   }

   答え = (strcmp(実数、チェック) == 0);

   答えを返す;
}
于 2008-11-04T16:11:32.273 に答える
0

これでうまくいくはずです:

bool isRepresentable(const char *realNumber)
{
    double value = strtod(realNumber, NULL);

    char test[20];
    sprintf(test, "%f", value);

    return strcmp(realNumber, test) == 0;
}

おそらく、潜在的なバッファオーバーランを防ぐために sprintf の「安全な」バージョンを使用するのが最善です (この場合でも可能ですか?)

于 2008-11-04T16:02:51.933 に答える
0

文字列を数値ビット表現 (ビット配列または long) に変換してから、文字列を double に変換して、それらが一致するかどうかを確認します。

于 2008-11-04T16:03:32.103 に答える
-2

文字列を double よりも大きなスコープを持つ float に変換します。それを double にキャストして、一致するかどうかを確認します。

于 2008-11-04T16:01:48.270 に答える