1

渡された数値 (inputValue) で最大の 1 桁を見つけることになっている関数を C++ で作成しています。たとえば、.345 の答えは 5 です。ただし、しばらくすると、プログラムは inputValue を .3449 の行に沿って何かに変更します (そして、最大の桁が 9 に設定されます)。なぜこれが起こっているのか分かりません。この問題を解決するための助けをいただければ幸いです。

これは私の .hpp ファイルの関数です

void LargeInput(const double inputValue)
//Function to find the largest value of the input
{
  int tempMax = 0,//Value that the temporary max number is in loop
  digit = 0,//Value of numbers after the decimal place
  test = 0,
  powerOten = 10;//Number multiplied by so that the next digit can be checked
  double number = inputValue;//A variable that can be changed in the function
  cout << "The number is still " << number << endl;
  for (int k = 1; k <= 6; k++)
  {
    test = (number*powerOten);
    cout << "test: " << test << endl;
    digit = test % 10;
    cout << (static_cast<int>(number*powerOten)) << endl;
    if (tempMax < digit)
      tempMax = digit;
    powerOten *= 10;
  }
  return;
}
4

4 に答える 4

1

実数 (double) をコンピューターで正確に表現することはできません。それらは概算する必要があります。関数を long または int で動作するように変更しても、不正確になることはありません。それはあなたの質問の文脈では十分に自然に思えます。数字ではなく数字を見ているだけなので、.345 は 345 になり、同じ結果が得られます。

これを試して:

int get_largest_digit(int n) {
  int largest = 0;

  while (n > 0) {
    int x = n % 10;
    if (x > largest) largest = x;
     n /= 10;
  }
  return largest;
}    
于 2012-10-12T00:50:25.103 に答える
0

残念ながら、これが浮動小数点数の仕組みです。問題の核心は、浮動小数点数が無限にあることです。より具体的には、0.1から0.2の間に無限の数の値があり、0.01から0.02の間に無限の数の値があります。ただし、コンピューターには、浮動小数点数を表す有限数のビットがあります(倍精度数の場合は64ビット)。したがって、ほとんどの浮動小数点数は概算する必要があります。浮動小数点演算の後、プロセッサは結果を64ビットで表現できる値に丸める必要があります。

浮動小数点数のもう1つの特性は、数値が大きくなるにつれて、精度が低下することです。これは、同じ64ビットが非常に大きな数(1,000,000,000)と非常に小さな数(0.000,000,000,001)を表すことができなければならないためです。したがって、数値が大きいほど、丸め誤差が大きくなります。

ここでのもう1つの問題は、浮動小数点から整数に変換していることです。これにより、さらに多くの丸め誤差が発生します。(0.345 * 10000)を整数に変換すると、結果は3450よりも3449に近くなるようです。

数値を整数に変換しないことをお勧めします。浮動小数点数の観点からプログラムを作成します。浮動小数点数でモジュラス(%)演算子を使用して、桁の値を取得することはできません。代わりに、C数学ライブラリ(cmath.h)のfmod関数を使用してください。

于 2012-10-12T01:26:19.640 に答える
0

他の回答が示しているように、2 進浮動小数点はほとんどの 10 進数を正確に表すことができません。したがって、問題のステートメントを再検討する必要があります。いくつかの代替手段は次のとおりです。

  • 数値は double (具体的には、64 ビットの IEEE-754 バイナリ浮動小数点値) として渡され、渡された正確な値の 10 進数表現で最大の桁を見つけたいと考えています。この場合、ユーザー millimoose によって提案された解決策が機能します (使用されるasprintforsnprintf関数が高品質であり、正しく丸められた出力の生成を妨げる丸め誤差が発生しない場合)。
  • 数値は double として渡されますが、既知の桁数の 10 進数として正確に表現できる数値を表すことを目的としています。この場合、ユーザー millimoose によって提案された解決策が再び機能し、必要な桁数で double を 10 進数に変換するようにフォーマット仕様が変更されます (たとえば、「%.64f」の代わりに「%.6f」を使用できます)。 .
  • 関数は、10 進浮動小数点、スケーリングされた整数、または 10 進数を含む文字列など、別の方法で数値を渡すように変更されます。

問題のステートメントが明確になったら、書式設定された出力に対してライブラリ関数を呼び出すのではなく、浮動小数点演算を使用して問題を解決する方法を検討することは興味深いかもしれません。これには教育的価値がある可能性があります (そして、偶然にも、ライブラリ関数を呼び出すよりも計算効率の高いソリューションを生成する可能性があります)。

于 2012-10-12T02:16:01.910 に答える
0

これは、実数の小数部分が 1/2^n の形式であるためです。その結果、目的に非常に近い値を取得できますが、1/3 のような正確な値を取得することはできません。

代わりに整数を使用し、変換 (1000 = 1 など) を行うのが一般的です。そのため、数値 1333 がある場合は、printf("%d.%d", 1333/1000, 1333 % 1000)1.333 を出力します。

ちなみに、最初の文は、浮動小数点数が実際にどのように表現されるかを簡略化したものです。詳細については、こちらをご覧ください。http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding

于 2012-10-12T00:57:09.313 に答える