1

float 値の小数点以下の桁数を計算する必要があります。

1234.567 -> 3 2.1233 - > 4
4.2432 -> 4

私の最初のアイデアは次のとおりです。

number = 1234.567;  
...  
while (number - (int)number > 0.0)  
{  
  // Count decimal places  
  ...  
  number *= 10;  
}

ただし、これにより、while 条件の float 精度に問題が生じます。唯一の安全な回避策は、float から string に変換してから、string ベースで小数点以下の桁数をカウントすることです。

問題は次のとおりです。サードパーティ製ライブラリも C++ 標準ライブラリも (環境上の制限により) ライブラリを使用してはなりません。後で char* を操作する方法は知っていますが、C++ ライブラリを使用せずに float 値を文字列 (つまり char*) に変換するにはどうすればよいですか?

どんな助けでも大歓迎です。


// 編集: これは私の現在のアプローチですが、まだ機能しません (例: 2.55555)。適切なしきい値を選択するにはどうすればよいですか?

float abs(float number)  
{  
  return (number > 0.0 ? number : number * -1);  
}  

int round(float number)  
{  
  return (int)(number + 0.5);  
}  

void splitFloat(float* number, int* mantissa, int* exponent)  
{  
  while (abs(*number - round(*number)) > 0.00001)  
  {  
    // *number -= (int)*number; // ???  
    *number *= 10.0;  

    *mantissa = *number;  
    *exponent += 1;  

    cout << "Number: " << *number << ", Mantisse: " << *mantissa << ", Exponent: " << *exponent << endl;  
  }  
}
4

3 に答える 3

5

あなたの最初のアイデアはかなり近いです。問題は、浮動小数点が丸めを行うため、結果が正確にならないことです。正確に 0.0 と比較する代わりにしきい値を使用する必要があり、(int)操作が誤って切り捨てられる可能性があることを許可する必要があり、代わりに丸める必要があります。切り捨てる前に 0.5 を追加することで丸めることができます。

また、桁数が収まらない場合にも問題が発生しintます。各ステップで数値の整数部分を差し引くことで支援できます。

編集:適切なしきい値を選択するには、処理する小数点以下の最大数を選択します。それが 4 の場合、出力する最小の数値は です0.0001。しきい値をその半分にするか、または0.00005. 数値を 10 倍するたびに、しきい値も 10 倍してください。

float threshold = 0.00005;
while (abs(*number - round(*number)) > threshold)  
{  
  *number *= 10.0;
  threshold *= 10.0;
  // ...
}

float と int が両方とも 32 ビットの場合、int の減算について心配する必要はありません。あなたがやっているように仮数を返すのが難しくなります。

また、前に警告するつもりだったのに忘れていましたが、これは正の数に対してのみ機能します。

もう 1 つの警告として、a の値の範囲floatは非常に限られています。1234.5670たとえば、正確に表すことができない場合があり、最後に余分な数字が表示されます。に変更するdoubleと、それが修正されます。

于 2012-03-23T17:53:02.997 に答える
1

あなたの元のアイデアは良いですが、最小限のエラーを想定する必要があります。

number = 1234.567;
...
while (fabs(number - round(number) > 0.00001)
{
    // Count decimal places
    ...
   number *= 10;
}

1234.567あなたが言うとき、コンピューターは1234.5670000001or1234.566999999と言うかもしれませんが、0 や 9 をたくさん数えたくないことに注意してください。

切り捨てではなく、ロンディングに注意してください。

ただし、負の数では期待どおりに動作しない可能性があることに注意してください。

于 2012-03-23T17:54:57.760 に答える
0

std::numeric_limits<float>::digits10 - log10(value)これは値が持つ10進数の最大値であるため、計算するのが最善だと思います。数値をフォーマットする必要がある場合は、この精度にフォーマットして末尾のゼロを取り除くことができます。値をフォーマットするものがない場合は、おそらく多くのことを行う必要があります。良い結果が必要な場合、アプローチは明らかに自明ではありません。

于 2012-03-23T18:28:28.730 に答える