0

浮動小数点数の基数の後の小数点以下の桁数を数えたいのですが。実数がのように2進法で表現されていない場合、問題は明らかに発生し3.5689113ます。

たとえば、誰かがこれをソースコードで実際に記述した場合、数値7、つまり小数点以下の桁数を取得できるかどうか疑問に思います。

たとえば、次のような単純なコードは機能しません。

int main()
{  
    double num = 3.5689113;

    int count = 0;
    num = abs(num);
    num = num - int(num);

    while ( abs(num) >
        0.0000001 )
    {
        num = num * 10;
        count = count + 1;
        num = num - int(num);
    }

    std::cout << count; //48
    std::cin.ignore();
}
4

4 に答える 4

3

そのようなことがうまくいかないときは、数字を印刷しようとします。

ここでそうしましたが、浮動小数点の精度に問題があることがわかりました。int丸めを丸めに変更しましたがceil、それは魅力のように機能しました。

sを元に戻してみるintと、次のように表示されます:)

編集: sを使用するよりも優れた戦略ceil(同じ丸めの問題が発生する可能性があります)は、数値を最も近い整数に丸めることです。あなたはでそれを行うことができますfloor(myNumber+0.5)

これが変更されたコードです

int main()
{  
    double num = 3.56891132326923333;

    // Limit to 7 digits
    num  = floor(num*10000000 + 0.5)/10000000;

    int count = 0;
    num = abs(num);
    num = num - floor(num+0.5);

    while ( abs(num) >
        0.0000001 )
    {
        cout << num << endl;
        num = num * 10;
        count = count + 1;
        num = num - floor(num+0.5);
    }

    std::cout << count; //48
    std::cin.ignore();

    return 0;
}
于 2012-10-26T22:34:07.130 に答える
3

浮動小数点近似によって発生するエラーを防ぐために、可能な限り早い機会に数値を整数に変換し、それを処理します。

double num = 3.5689113;

int count = 7;  // a maximum of 7 places
num = abs(num);
int remainder = int(0.5 + 10000000 * (num - int(num)));

while ( remainder % 10 == 0 )
{
    remainder = remainder / 10;
    --count;
}
于 2012-10-26T22:54:06.493 に答える
1

浮動小数点型のT場合、最大でstd::numeric_limits<T>::digits10数字を正確に復元できます。したがって、ゼロ以外の最後の小数桁の位置を決定するには、この値を精度として使用し、数値をフォーマットします。指数表記を使用した出力を回避するには、フォーマットフラグをに設定しstd::ios_base::fixed、非小数桁数を考慮する必要があります。

std::ostringstream out;
int non_fraction(std::abs(value) < std::numeric_limits<double>::epsilon()
                 ? 1: (1 + std::log(std::abs(value)) / std::log(10)));
out << std::setprecision(std::numeric_limits<double>::digits10 - non_fraction)
    << std::fixed
    << value;

小数点がある場合は、ゼロの末尾のシーケンスまでの桁数を数える必要があります。

于 2012-10-27T01:48:03.783 に答える
0

文字列に変換し、それをループして、ピリオドに達した後に発生する文字数を数えることをお勧めします。以下はサンプルです(C ++でこれを行ってからしばらく経ちましたが、多少の調整が必要な場合があります)。

bool passedRadix = false
int i = 0; // for counting decimals
std::ostringstream strs;
strs << dbl; // dbl is 3.415 or whatever you're counting
std::string str = strs.str();

for(char& c : str) {
   if (passedRadix == true)
       i++; 
   if (c == '.')
       passedRadix = true;

}
于 2012-10-26T22:31:22.397 に答える