1

今、私は次のようにやっています:

uint8_t ManualFlow = 40; // 0 -> 255     Unsigned Char

uint24_t ME; // 0 -> 16777215 Unsigned Short Long
ME = (uint24_t) ManualFlow*10; // Have to make this hack otherwise malfunction in calculation
ME /= 6;
ME *= (80 - 60);
ME /= 100;
ME *= 414;

最終結果:

40*10 = 400
400/6 = 66
66*20 = 1320
1320/100 = 13
13*414 = 5382

私が好きなものはこれに似ています:

4/60 = 0,0667 * 20 * 4188 * 0,998 = 5576 (more accurate).

floatsまたはsを使用せずにこれをより正確に行うにはどうすればよいですかdouble。最も重要なのは、コードサイズを大きくしすぎないことです。

よろしくソナイト

4

6 に答える 6

4

固定小数点演算を確認することをお勧めします。

http://en.wikipedia.org/wiki/Fixed-point_arithmetic

また、WG14のテクニカルレポート18037(最新バージョンのISO / IEC TR 18037:2008は残念ながら無料ではありません):

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf

于 2012-04-02T21:52:02.293 に答える
1

結果がオーバーフローしないことが確実な場合は、除算の前にすべての乗算を実行します。

uint24_t ME;
ME = (uint24_t)ManualFlow*10;
ME *= (80 - 60);
ME *= 414;
ME /= (6 * 14);

整数以上の精度が必要であるが浮動小数点を避けたい場合は、代わりに固定小数点演算の使用を検討してください。

于 2012-04-02T21:54:19.310 に答える
1

(浮動小数点ではなく)固定小数点演算を参照しています。整数のサイズをuint64_tのようなものにいつでも増やし、10を超えて乗算して、目的の精度を達成できます。

ただし、2進数の固定小数点を使用することをお勧めします(つまり、10を特定の累乗するのではなく、特定のビット数だけ左にシフトします)。それは(はるかに)高速であり、より正確になる可能性があります。

于 2012-04-02T21:55:24.957 に答える
0

すべての入力にたとえば(1 << 8)を掛けてより大きなデータ型にし、必要な計算を行ってから、答えを(1 << 8)で割ります。

于 2012-04-02T21:52:43.650 に答える
0

結論:

私の最初のコードはそれほど正確ではなく、「これほど大きい」ものでした。

以下でこれを行うことにより、「38バイト」でコードを増やし、精度を向上させました

ME = (uint24_t) ManualFlow*100;
ME /= 6;
ME *= (Port[2].AD - Port[3].AD);
ME /= 100;
ME *= 414;
ME /= 10;

固定小数点を実行することで得られた最高の精度ですが、コードが「1148バイト->」に増加しました。

// Utility macros for dealing with 16:16 fixed-point numbers
#define I2X(v) ((int32_t) ((v) * 65536.0 + 0.5))    // Int to Fix32
#define X2I(v) ((int16_t) ((v) + 0x8000 >> 16))     // Fix to Int

ME = I2X(ManualFlow*10); //400 * 65536.0 + 0.5 =   26214400
ME = I2X(ME/6); // 26214400 / 6 = 4369066
ME = I2X(ME * 20); // = 87381320
ME = I2X(ME / 100); // = 873813
ME = I2X(ME * 414); // 361758582
ME = X2I(ME); // 158FFF76 + 8000 >> 16 15907F76 >> 16 = 5520

それが他の誰かを助けることができることを願っています!

よろしくソナイト

于 2012-04-03T09:37:19.900 に答える
0

元のポスターについて回答するのは少し遅れるかもしれませんが、後世のために、小さなプロセッサで速度が非常に重要な場合は、固定小数点除算も回避できる場合が多いことにも注意してください。変数による除算は避けられないことがよくありますが、定数による除算の代わりに(ほとんど)常に乗算とシフトを使用できます。これは、特に小さなプロセッサのデータ幅よりも大きいタイプの場合、多くのプロセッササイクルを消費する可能性があります。それ以外の

uint16_t x = somevalue;  //somevalue known to be between 0 and 65535
x /= 107;

次を使用できます。

uint32_t x = somevalue;
x *= 39199;  //chosen to be 2^n/107
             //n chosen to maximum value without exceeding 65536
x >>= 22;    //n = 22 in this case

注:これは読みにくいコードですが、パフォーマンスが重要なアルゴリズムである場合は、この最適化を(控えめに)使用できます。

于 2012-05-04T03:22:17.313 に答える