• ベストアンサー

1.15倍や0.3倍のコード

1.15倍や0.3倍のコード マイコン(R8C)で1.15倍や0.3倍などを表すのに一番効率が良いコードはどう書けばいいのでしょうか? 1.15や0.3倍する数はint型で小数点以下を四捨五入したいと考えています。 2倍や0.25倍ならビットシフトを利用すると思うのですが、上記の場合はどうすればいいのか解りません。 マイコン初心者で恥ずかしい限りですが、何卒よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

桁あふれしないなら、115倍して50を足して100で割ります。 int a=444; a = ((a * 115) + 50) / 100; 0.3倍も似たような考え方です。 int b=777; a = ((a * 3) + 5) / 10;

new_okwave
質問者

お礼

zwi 様 ご回答ありがとうございます。 上記方法で試したら、コード量が激減しました。 しかし、なぜ5や50を足しているのでしょうか。 教えていただけると助かります。

その他の回答 (7)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.8

>0.5(50)を足しているのはなぜですか。四捨五入のためですか。 はい。そのとおりです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.7

「1.15倍の計算結果の後に四捨五入をしたい」とはどういうことでしょうか? もちろん浮動小数演算すれば可能ですが, 整数で計算する限り不可能です (四捨五入するために必要な情報が消えてしまっている). で #5 のコードはちょっと考えればわかるはずです. 10の倍数は 0.3倍しても整数のままなので, それをまず計算する. 一方 10 で割った余りのところは 0.3倍したときに小数になるのでそこを四捨五入した結果を加える, ただそれだけ.

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.6

私のコードのポイントは小数点以下が無いなら100倍すれば少数以下を仮想的に持つことが出来るってことです。 式をこう考えただけです。 int((x * 1.15) + 0.5) = ((x * 115) + 50) / 100

new_okwave
質問者

お礼

zwi 様 度々のご回答どうもありがとうございます。 1.15を115/100と考えたということで良いでしょうか。 0.5(50)を足しているのはなぜですか。四捨五入のためですか。 一応1.15倍の計算結果の後に四捨五入をしたいと思います。 何卒、ご教授の程お願い致します。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

一口に「効率」といってもいろいろな指標がありますね. さておき, たとえば 0.3倍するなら const int three_tenth[] = { 0, 0, 1, 1, 1, 2, 2, 2, 2, 3 }; と準備して (x/10)*3 + three_tenth[x%10] ともできますね. x/10 と x%10 はアセンブリなら一発, そうでなくても div が使えるかもしれません. 「アセンブリで書く」という方針もある....

new_okwave
質問者

お礼

Tacosan 様 ご回答ありがとうございます。 私の頭では、上記式がなぜ0.3倍になるのかがわかりません。 また、アセンブリは書けませんしC言語もまだまだです。 もしよろしければ、上記式の導き方を教えてください。 よろしくお願い致します。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.4

固定小数点で考える方法もあるかと。 シフトと加算に展開することも可能です。

new_okwave
質問者

お礼

titokani 様 ご回答ありがとうございます。 固定小数点やシフトと加算に展開とはどのようにするのでしょうか。 もしよろしければご教授願います。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

もう少しひねって少々の誤差覚悟なら、 #define BAIRITU (115*0x80/100) a = ((a * BAIRITU) + 0x40) >> 7; これなら割り算は発生しません。

new_okwave
質問者

お礼

zwi 様 度重なるご回答ありがとうございます。 なぜ上記式が成立するのでしょうか。 出来れば教えてください。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

まず係数を整数に直すために必要な最小の10^nを求めます。 求めたら、その数で係数を整数化し、掛算を行います。 その結果を10^(n-1)の桁で四捨五入し、最後に10^nで割れば答えが出ます。 この計算のキモは、「FPUのないマイコンでの浮動小数演算は遅いので整数演算のみで片付ける」というところです。

new_okwave
質問者

お礼

D-Matsu 様 ご回答ありがとうございます。 なるほど、マイコンで浮動小数演算は避けたほうがよさそうですね。 ありがとうございます。

関連するQ&A