4

私は c++ での OpenGL の初心者向けチュートリアルに従っていますが、ac# プログラマーとして始めたので、多くのことを当然のことと考えてしまいました。そのため、FPSの読み取り値を出力にデバッグ印刷しているときに問題が発生しました。メソッドは頭のてっぺんから DebugPrintString のようなもので、char* を受け取り、基本的に「FPS: x」を出力していたと思います。scanf_s を使用して fps 値を文字配列に配置していましたが、ここに問題があります。文字配列の大きさはどのくらいですか?

もう少し詳しく説明しましょう。通常、フレーム/秒は適切な数値ではないため、私の FPS の読み取り値は float として保存されます。つまり、私の番号は 60 かもしれませんし、59.12345 かもしれません。60 には 2 バイトしか必要なく、59.12345 には 8 (ピリオドに 1) が必要です。それで、「ああ、桁数を数えなければならない、問題ない!」と思いました。男の子は私がショックを受けていました。

桁数を数える方法を作成しました。小数点以下の左側を数えるのは簡単でした。まず、整数としてキャストして小数点を削除し、10 で除算します (実際には、ビットシフトがあったと思います)。 0 になるまで何回できるかを数えます。右辺の桁を数えます。10 を掛けて、その桁を引きます。これを 0 になるまで繰り返します。このメソッドは通常 32 を返します。それで、私はWTF'dしてデバッグでそれを見ました.浮動小数点数を掛けると、よく知られている精度の問題のために数字の列を効果的に上に移動すると、別の数字が追加されたことがわかりました!

私はいくつかの主要なグーグルを行いましたが、実際には char str[128] と scanf if in then do strlen(str) - 1 (null ターミネータ) の上に何も見つかりませんでした。しかし、私はよりエレガントなソリューションを望んでいました。最後に、それをintとしてキャストし、9999 fpsに十分な値を許可し、fps> 9999かどうかを確認するチェックも追加しましたが、それが起こるとは思いません. SEG FAULTよりも安全です:(

TLDR: float の桁数を取得する方法はありますか? scanf はどのようにそれを行いますか?!

長い投稿で申し訳ありませんが、私の欲求不満を共有したかっただけです >:D

編集:スペルミス

4

5 に答える 5

7

私たちが話しているのは C++ であることを考えると、なぜ STL の方法を採用しないのでしょうか?

小数点以下 5 桁の精度。文字数は可変の場合があります。

std::stringstream ss;
ss << std::setprecision (5) << std::fixed << f; 
std::string fps = ss.str();

精度最大有効数字 5 桁:

std::stringstream ss;
ss << std::setprecision (5) << f; 
std::string fps = ss.str();
于 2010-01-28T00:06:56.763 に答える
6

sprintfを使用して、浮動小数点数を任意の精度に切り捨てる/強制することができます。その後、問題は解決します。

于 2010-01-27T23:58:07.987 に答える
1

浮動小数点数は正確に格納されないため、桁数を数える効果的な方法は実際にはありません。おそらくやりたいことは、floatが提供する数値の長さを制御し、固定サイズのバッファーを使用することです。

printf()、および関連する関数を使用scanf()すると、形式タイプ指定子を変更することにより、浮動小数点数のサイズを指定できます。単純な%fものが最も一般的かもしれませんが、%との間に次のfような修飾子を追加することで、より柔軟に使用できます。

%[width][.precision]f

ここで、は数値に対して表示[width]する最小桁数を示し(それを超えても切り捨てはありません)、[.precision]小数点以下に表示する正確な桁数を指定します。

例として、次のプログラムの出力を調べることができます。

#include <cstdio>

using std::printf;
int main() {
  float f(59.12345);

  printf("[%f]\n", f);    // [59.123451]
  printf("[%15f]\n", f);  // [      59.123451]
  printf("[%1f]\n", f);   // [59.123451]
  printf("[%.2f]\n", f);  // [59.12]
  printf("[%6.2f]\n", f); // [ 59.12]
  printf("[%4.1f]\n", f); // [59.1]
}

文字配列の正確なサイズは、小数点以下の値に応じて変動します。ただし、幅と精度を制御できる限り、十分なメモリを文字配列に割り当てる(または数値を固定長配列に合わせる)方がはるかに簡単です。

于 2010-01-28T00:42:10.833 に答える
0

CashCommonsのジョンは伝統的な答えを出しました.printfフォーマット修飾子を使用して特定の幅を強制するだけです. 通常、フレーム レートは小数点以下 2 桁で十分です。最も一般的な 2 つの値である 30 fps と 29.97 fps を区別できます。

 sprintf (buffer, "%.2f", fps);

しかし、最悪のケースが何であるかを知りたい場合は、それを知る方法もあります。http://en.wikipedia.org/wiki/IEEE_754-2008をチェックしてください。

これは、浮動小数点値 (32 ビット浮動小数点数) の仮数部に 24 桁の 2 進数があり、10 進数で 7.225 桁になることを示しています。これを 8 と呼びます。指数に 5 桁、符号に 1、先頭の 0 に 1 を追加します。小数点のために、あなたは得る

 1 + 1 + 8 + 5 = 15 characters

終端ヌルの余地を追加すると、16 桁になります。

于 2010-01-28T00:57:35.037 に答える
0

1 秒あたりのフレーム数です。左に 3 桁、右に 1 桁を使用するだけです。

最初のコメントに応じて編集します。

http://en.wikipedia.org/wiki/Floating_point

浮動小数点数の桁数が本当に必要な場合は、浮動小数点数がどのように機能するかを知る必要があります。IEEE 標準 float データ型で表される正確な値には、一定量のビット (通常は 32 または 64) があり、標準化された方法で割り当てられて、一定量の有効桁数と、それをスケールアップまたはスケールダウンするための累乗指数が得られます。24 ビットの有効桁数は、小数第 7 位まで出てきます。コースの終わりには常に何らかの形の切り捨てまたは丸めエラーが発生します (たとえば、10 進数で書かれた 3 分の 1 は、3 の繰り返しを書くのをやめると常に切り捨てられます)。

数値が 7 桁または 8 桁で停止する可能性がありますが、機械の丸め誤差により、偶発的に数値が継続することはありませんか? その種のデータを読み取るだけでは意味がありません。

于 2010-01-28T00:20:15.307 に答える