トピック
みむ*mim hidemimtp

LOG(1000,10)って・・・

?LOG(1000,10) 3 ?FLOOR(LOG(1000,10)) 2 これは以前どなたかが話題にされていた内部的な仕様で、仕方ないんですかねぇ・・・
1そうだね
プレイ済み
返信[1]
親投稿
MIKI ifconfig
log(1000,10) の計算結果は 3 未満なのに、 print 命令が勝手に有効数字 6 桁に丸めてるだけですからねえ。 floor 使うときは常に留意しとかないと予想外の結果になります。 連続秒数から時:分:秒に変換する時とか、よくハマりますね。 ? format$("%.18f", log(1000,10)) 2.9999(略)99600 がより正確な値です。 自分が欲しい精度で丸めるのがいいんじゃないかな?? 例えば丸め幅 = 0.001 で丸めるなら 1000 倍して四捨五入して 1000 で割ればいいでしょう。 ? format$("%.18f", floor(log(1000,10)*1000+0.5)/1000) 3.0000(略)0000
0そうだね
プレイ済み
返信[2]
親投稿
みむ*mim hidemimtp
以前書かれていたのはMIKIさんでしたっけ? 何となく予備知識があったので深みにはまらず回避できました。 丸めというか、10進数の桁数分、ループを回したかったんです。 FOR I=0 TO LOG(V,10) これだと、 999・・・3回 1000・・・3回 1001・・・4回 回るので、1000の時は想定外でした。 なので今は整数限定という事にあぐらをかいて、 FOR I=0 TO LOG(V+0.1,10) と適当に足してやっていますが、スマートじゃないですね。
0そうだね
プレイ済み
返信[3]
親投稿
MIKI ifconfig
こういうエサにホイホイ食いついてくるのは私かおちゃめさんです! きっとおちゃめさんが最適解をご存知でしょう! 私だったら for i = 0 to len(format$("%.0f",v))-1 で満足! 浮動小数でもいけます!
0そうだね
プレイ済み
返信[4]
親投稿
みむ*mim hidemimtp
なーるほど。ありがとうございます。 ちなみになぜ桁数分回したかったかと言えば、 数値に3桁ごとにカンマを入れたかったのですが、桁が大きくなると、 ?STR$(11111111111) ’11桁 1.11111e+10 なんていう余計なことをしてくれるので、その回避なんです。 これだけなら、LOGを使う方法をやめた方がいいかもですね。 2分割したり方法は色々ありそうです。
0そうだね
プレイ済み
返信[5]
親投稿
おちゃめ ochame_nako
プチコン3号は内部ではすべて2進数で処理されている関係上実数型による計算は常に誤差が発生する可能性があります。 例えば0.1が2進数では循環小数になる関係で「0.1を100回足す」という単純な動作でさえ10ちょうどにはならないのです 詳しくはこちらのトピックスに書いていますが、より詳しく知りたいならば「プチコン3号 実数型 誤差」などでネット検索してください。 https://miiverse.nintendo.net/posts/AYIHAAAEAAASVZKdAWi67g
1そうだね
プレイ済み
返信[6]
親投稿
おちゃめ ochame_nako
誤差が発生するのは仕様であるため仕方がないのですが、これは誤動作が起きないように対策をすれば良いので難しくありません。 この対策には様々な方法があり、みむさんが書いておられるLOG(V+0.1,10)というのもVが整数限定ならば問題ないと思います。 ただし、プチコン3号の場合は数値を表示する際にはご丁寧に丸めてくれるためその問題に気づかないことの方も多いでしょう。 その問題の解決方法の1つとして「丸められた表示通りに処理をしてしまえば丸く収まる」ということで以前PR関数を作りました。 https://miiverse.nintendo.net/posts/AYIHAAAEAADaVHh0IAWNUQ
1そうだね
プレイ済み
返信[7]
親投稿
おちゃめ ochame_nako
といっても、PR関数の原理そのものは単純でMIKIさんが書かれている「欲しい精度で丸める」を実行しているだけです。 プチコン3号では絶対値1E8未満の値の時は小数第9位を四捨五入された値になっているのでPR関数ではそうなるように丸めています したがって、使う回数が1回だけならばわざわざ関数化しなくても変数Aに演算結果が入っている場合はROUND(A*1E8)/1E8とするだけで表示された数値通りの処理を行うことができます。 最適解というのはやっている処理や求めるものによって変わります。 MIKIさんが書かれている方法も私が書いている方法も解決方法の1つにすぎません。
1そうだね
プレイ済み
返信[8]
親投稿
おちゃめ ochame_nako
STR$の丸め処理に関しては整数型変数もしくは整数の定数においては整数型の上限までは丸め処理を行わずに全桁表示されます。 しかし、実数型変数(デフォルトの変数)や小数点が付いている定数、整数型の範囲を超えた定数に関しては自動的に6桁に丸められます。 これを回避するにはFORMAT$を使えばいいのですが、FORMAT$にも問題点がありプチコン3号の内部の数値から誤差ゼロで文字列化する方法として用意したのがPSTR$関数です。 https://miiverse.nintendo.net/posts/AYIHAAAEAABEVRTp-ZVMIg PSTR$(LOG(1000,10))とすれば表示で丸められる前の値がどのような値になっているかが分かります。
0そうだね
プレイ済み
返信[9]
親投稿
おちゃめ ochame_nako
このPSTR$のリストを見てもらえば分かるのですが、桁数を求めるのにLOGを使わず文字列操作のみで行っています。 簡単に説明するとこれは小数点がある場所を基準にしてそこから桁数を導くという方法です。 PSTR$のような実数型でも正しく表示するのが目的ならばこれがベストですが、これはみむさんが求めているものに対してはベストとは言い難いです。
1そうだね
プレイ済み
返信[10]
親投稿
おちゃめ ochame_nako
扱うのが整数値で3桁ごとに「,」を入れたいというのであればその数値の下位3桁を取り出す→取り出した後の値が0ならば取り出した数字を文字列化して先頭に加えて終了、そうでないならば数値を1000で割り整数化し、取り出した3桁の数値を3桁で文字列化して「,」を頭にけるという処理を繰り返すのが2つの問題点を同時に解決できる手段であり分かりやすさも兼ねそろえた解決方法だと私は思います。 これならば9007199254740992までの数値は正しく表示可能です。(それを超えても表示が可能になるけど正確さは保証されない) 迷ったときは最もシンプルな方法を採る(LOGで誤差が出るならばLOGを使わない)のが間違いが起きにくいです。 負数の場合はあらかじめ正数にしておいて後からマイナスの符号を付けてください。 ちなみに数値を3桁で文字列化するにはFORMAT$("%03D",A)で可能です。
1そうだね
プレイ済み
返信[11]
親投稿
みむ*mim hidemimtp
おちゃめさん 待ってました(笑)詳細な解説、ありがとうございます。 PSTR$、そういう事だったのですね。 誤差の問題もある程度知っておく必要がありますが、 3桁区切りでこの問題と戦う必要はなさそうですね。 LOGを使えばわざわざ分割しなくてもと思ったのですが甘かったです。 まぁ誤差は仕様としても、STR%はeを使わず返す、FORMAT$に3桁区切りするなどの機能は欲しいなぁ。
0そうだね
プレイ済み
返信[12]
親投稿
みむ*mim hidemimtp
追伸 ?STR$(1111111) 1111111 V=1111111 ?STR$(V) 1.11111e+06 これも何だか変ですね。
1そうだね
プレイ済み
返信[13]
親投稿
みむ*mim hidemimtp
V%=1111111 ?STR$(V%) 1111111
1そうだね
プレイ済み
返信[14]
親投稿
(いまさらこのトピックを見て「そんなとこにも誤差あったの」と驚いてる人)
3そうだね
プレイ済み
返信[15]
親投稿
おちゃめ ochame_nako
上記のアルゴリズムによるCOMMA関数をこちらのトピックスで書きました。 https://miiverse.nintendo.net/posts/AYMHAAACAAADVHkyf3cD3A
1そうだね
プレイ済み
返信[16]
親投稿
おちゃめ ochame_nako
誤差を無くすのは無理ですが、FORMAT$の3桁に対応させるのは難しくないのでぜひ対応して欲しいですよね。 しかし、すぐに指数表記になるSTR$、絶対に指数表記をしないFORMAT$と両極端なので使い分けは慣れが必要だと思います。 そういう意味ではPSTR$は可能な限り指数は使わず、必要な段階で指数表記にするので優しいです。
1そうだね
プレイ済み
返信[17]
親投稿
マギー M191246
簡易版になりますけど 試しに、違うアプローチで 3桁区切りの関数を作ってみました。 FORMAT関数の精度の限界内なら 使えるんじゃないかと思います。
1そうだね
プレイ済み
返信[18]
親投稿
みむ*mim hidemimtp
マギーさん すばらしい。王道な感じですね。単純で美しいです。 %.F も、なるほど。 やめかけていた電卓作り、もうちょっと続けてみたくなりました。
1そうだね
プレイ済み