こんにちは、NAKAといいます。C言語基礎を確認させてください。
pow()っていう関数を使うと思うのですが
例えば2^15って0x8000だと思うのですが、実際やってみると0x7FFFになってしまいます。
NAKAさん、こんにちは。Sugachanceです。
NAKAさんの場合、RL78なのかRXなのかRH850なのかはたまた他のやつなのか…分かりませんが、手元のRL78の環境の場合仰るように0x7FFFになりました(intに渡した時)。pow()関数自体、引数も戻値もdouble型ですが、RL78の環境だとdoubleはfloatと同じ4バイト(だった気がするので)そのあたりの精度・切り捨てとキャストの兼ね合いな気がします。
double ans;int ansi;ans = pow(2,15);ansi= pow(2,15);
の結果をウォッチで見てみたらans 3.276798E+004 float(4)ansi 32767 (0x7fff) int(2)
ってなってました。先日、Cに関して素人レベルだと怒られてしまったのでプロレベルの詳しい方の解説が欲しいところです!
doubleのオプションを付けたらans 3.276800000000004E+004 double(8)ansi -32768 (0x8000) int(2)になりました!
Sugachanceさん お久しぶりです。ナカです。いつもありがとうございます。僕も、基礎がないのですぐつまずいちゃいます。
じつは先日までpow関数も知らずに A=2^15;とか書いちゃって「おかしいなあ計算結果が全然ちがう!」とかやってました(*_*)ビルドでエラーが出ないと正しいと思いこんじゃいますね。
NAKAさん、こんにちは
RL78とすれば、「CC-RL コンパイラ ユーザーズマニュアル」あたりから確認するものではないでしょうか。
手元の Rev.1.11 (2021.11) 「4. コンパイラ言語仕様」を見ると、int は、2バイトで、先頭1bitが符号ビットなので、正数の最大値は、0x7FFF(32767) となり、多分、丸めでしょう。double → intの丸めが見つからならなかったのですが、正数の最大値かな、と。
この辺は、C言語というより、実装依存かな、と思う次第です。
マニュアルを見ると、pow関数は、double を引数にとって、doubleを返します。
戻り値をintに代入しているので、double → intの変換が入ります。
なお、intは、C言語の規則としては、 short ≦ int ≦ long となっていて、16bit CPU以下では、16bitが多く、 32bit以上では、32bitが多いようですが、処理系依存。
あと、RL78だと、レジスタが16bitまでしかないので、double(64bit) 以前に float(32bit)も使いたくない、、というなのが、個人的な気持ち。
Sugachanceさん NAKAです。
>doubleのオプションを付けたら⇒ってどこのオプションでしたっけ? プロパティのコンパイラ・オプションくらいかなと早合点してました。
やっぱり、なんか変です。
pow(2,2)=0x3になっちゃうし
mathfをインクルードたら更におかしなことになりました。
RL78でもRH850でも同じ感じでした。
0.5乗は上手くいく!
やっぱり、変
NAKAさん、こんにちは。NoMaYです。> 数学的本質みたいなのは理解できてませんが、この文面を見た時、これは分かっていないサインかな、と感じたのですけれども、そういうことだったな、と思いました。数値計算の分野では、浮動小数点数での数値計算ライブラリの計算結果が、机上の計算結果とは一致しないことがある、というのは常識といってもよいようなことなのです。(例) 実際に計算していないので、たまたま、うまくいくこともあるかもしれません。(1) 0.001を1000個足したからといって、1.000(それ以下の桁は省略) になるとは限らない(2) √2 × √2 = 2 ではあるけども、SQRT(2.000) × SQRT(2.000) = 2.000(それ以下の桁は省略) になるとは限らない(3) 2の2乗 = 4 ではあるけれども、POW(2.000, 2.000) = 4.000(それ以下の桁は省略) になるとは限らない
NAKAさん こんにちは。Sugachanceです。私がいじったのはコンパイルオプションのdouble型/long~のところです。正しくはつけたらというか、いいえにしたらですが…
NoMaYさん いつもありがとうございます。 NAKAです。
数値計算関数は浮動小数点で作られているので、浮動小数点自体が仮数部で表現できるのに限界があるため、誤差が発生し、必ずしも机上計算どうりにはいかないという理解でしょうか?
元々、北米の有名大学の先生(ソフトの専門ではない)が書いたコードで先頭のbitの符号を確認するのに2^15(0x8000)をandしているような書き方だったで、論理演算のためFloatで誤差を少くしても意味ないし、int型をビットシフトしたり、色々悩ましいです。(;_;)
NAKAさん、こんにちは。NoMaYです。> 北米の有名大学の先生(ソフトの専門ではない)が書いたコードちなみに、その先生がコードを書くのに使用されていたプログラミング言語は何ですか?また、可能であれば、原著へのURLもあれば、と思います。
NoMaYさん NAKAです。すみません!NDA締結した共同研究先なのであまり情報は出せません。C言語的な感じですが指示書みたいなものです。
Sugachanceさん
⇒ありがとうございました。♡ RH850のプロパティ見てました(*_*)