コミュニティアイコン プチコン 非公式コミュニティ プレイ日記

アバター
あまさとしおん ◆mzDKTVUAtwqE
2021/1/16 16:00
トピックに反応しようとしたら閉じられてるの悲しい
http://petitverse.hosiken.jp/community/petitcom/topic/?read=1629

いや、問題の具体的な解消法を分かってないのに閉めるかよ
「見た目通り」に取り出したいならFORMAT$()で文字列化して、目的の桁を切抜いてから数値に戻すのが安全な方法。

コメント

アバター
あまさとしおん 2021/1/16 16:37 ◆mzDKTVUAtwqE
例えば
VAL(RIGHT$(FORMAT$("%3.F",value),2)[0])
とか
※四捨五入を避けるために1桁多く整形してから切り出している
小数第2位なら%3.F
小数第3位なら%4.F
つまり小数第n位の時、n+1が「%と.Fの間」に入れる数字になる
アバター
さすらいの名無し 2021/1/16 17:51 ◆LWMA5UzCJb3e
閉じられてるのは実際、自分も思いました。
なんで自分の回答だけで閉じたのか。それがそもそも正しいのか分からない(というか自分が書いたことが正しいのかどうか不安)し、他の人の回答も見た方がいいのでは?って感じで。
アバター
チゲ 2021/1/16 22:14 ◆WZeL9z8yLqFX
あぁすいません、「小数演算の誤差」で調べて出てきたページが分かりやすくて解消法も載ってたので半分自己解決のような形で閉じてました
確かにあそこで閉めると自分以外の人が読んだらモヤモヤしますね
アバター
ツララ 2021/1/17 10:00 ◆ArUdBYOYME1V
何かチゲさんなりの理由があってコメント閉め切ったんでしょうから
そこを咎めるのは如何なものかと
閉じられてる投稿にコメント付けたくなったならリンクを貼って新しく代走投稿すればいいだけですし
投稿主がトピック自体を削除するよかマシかと

で、件のチゲさんの計算式
PRINT (N+0.06)*100 MOD 10
ここでNが4未満だと結果が6でNが4以上だと結果は5になる真相って具体的に何だったんです?
自己解決したんなら説明可能ですよね
アバター
チゲ 2021/1/17 11:24 ◆WZeL9z8yLqFX
「そういう誤差がある」ってのを知った時点で納得しちゃったのであまり自信無いですけど
浮動小数点演算の時、4.06だと
1×1.015×2^2
として扱われ、3.06だと
1×1.53×2^1
として扱われるので、ここで2を2乗以上してるかしてないかが丸め誤差が発生するかしないかの変わり目になったんだと思います
アバター
Na 2021/1/18 23:15 ◆QoELVrBXBQCI
その理論だとNが4以上なら必ず結果が5になるということになりますが、
実際は
N=4〜5 → 結果5
N=6〜15 → 結果6
N=16〜20 → 結果5
N=21〜511 → 結果6
N=512〜655 → 結果5
となりました。
誤差が発生するのは指数の方ではなく、その前の「1.015」や「1.53」の部分だと思います。
コンピューターでは小数も2進法で表すので、
1.015を2進法に直すと、
1.00000011110101...と割り切れない数になります。
これをある桁までで四捨五入(2進数だから0捨1入かな?)するため、
わずかな誤差が出ます。
(調べたところ52桁までだそうです。)
アバター
チゲ 2021/1/19 20:39 ◆WZeL9z8yLqFX
なるほど、やっぱり早合点が過ぎたみたいですね。6から15で試しておけばよかった…

ちょっと言い訳をさせてもらうと何か新しいバグを見付けたと思って内心盛り上がっていたら、コンピュータにはありがちな単なる誤算だと知って恥ずかしくなったのも閉めた理由だったりします
アバター
Na 2021/1/19 21:02 ◆QoELVrBXBQCI
よく考えたら上の説明だとN=5と6で結果が違う理由が説明できてませんでした。
N+0.06 は ((N+0.06)/2^n) × 2^n で表されるはずですが、
N/2^n の部分は2進数なら小数n桁で必ず表せるので、
4.06でも5.06でも6.06でも小数第53位まで変わるということはないはずです。
例えば
4.06=1.015×2^2
5.06=1.265×2^2
6.06=1.515×2^2
で、小数の下の方の桁は変わりません。
なので結果に違いが出るとしたら「×100」をした時点だと思います。
100=1.5625×2^6 なので、
4.06×100=(1.015×1.5625)×2^(2+6)
 =1.5859375×2^8
5.06×100=(1.265×1.5625)×2^(2+6)
 =1.9765625×2^8
6.06×100=(1.515×1.5625)×2^(2+6)
 =2.3671875×2^8
 =1.18359375×2^9
仮数部(小数の部分)が2以上になると指数が1繰り上がり、
仮数部は半分になるので、2進数で表すと1桁繰り下がります。
この時に5.06の場合と6.06の場合で小数の下の方の桁まで違いが出てくるのだと思います。
(実際にプチコンの小数の細かい値を見て違いを確認したわけじゃないので、違ってたらすみません。)
アバター
ツララ 2021/1/28 14:53 ◆ArUdBYOYME1V
ところでチゲさんは、あまさとしおんさんが提案してくれている方法について何かコメント無いんですか?
せっかく詳細な説明もしてくれているのに、ノーリアクションはあんまりだと思うんですけど。

チゲさんも今回の件で、恥ずかしいからってすぐ閉めちゃう方がもっと恥ずかしいって分かったでしょ?
恥ずかしい時はちゃんと「恥ずかしい///」って隠さず言っちゃって、客観的な反応貰った方が恥ずかしくないんです。(個人差有り)
エロも隠した方が余計エ(自粛
アバター
チゲ 2021/1/29 18:36 ◆WZeL9z8yLqFX
あっ、完全に調べた方法で満足してて忘れてた…

何気に[x]でx文字目の文字列抜き出せるの初めて知りました。今までMIDを使ってた所がスマートになりそう
自分はFORMATよりもSTRをよく使うんですけど、やっぱりバグりにくさならFORMATなんでしょうか

ちなみに自分が調べた方法はそもそもデータを実数じゃなく整数で扱うってやつです。
アバター
あまさとしおん 2021/1/29 20:23 ◆mzDKTVUAtwqE
STR$()は勝手に6桁ぐらい(おおまかな認識)で丸められるので、任意の「小数第〇位」に対応する見込みがあればFORMAT$()を使った方が安全です。
アバター
チゲ 2021/1/30 11:11 ◆WZeL9z8yLqFX
ありがとうございます
アバター
さすらいの名無し 2021/2/9 16:04 ◆LWMA5UzCJb3e
[x]でx文字目が取り出せるの、仕様理解してないと分からない(実際自分も分からないし、落とし穴があるみたいなこと聞いたことある)ので、MID$使った方が安全だと思う。
アバター
あまさとしおん 2021/2/10 23:30 ◆mzDKTVUAtwqE
添字表記で発生する落とし穴があるとすれば、参照型に関連する諸々の罠があるといえばありますが、この場合、FORMAT関数を挟んでる時点で参照が解除されるため、心配する要素は全くありません。
また、文字数が足りないときにsubscript out of rangeでエラーになる問題がありますが、固定長で整形をしている時点でその危険もありません。
アバター
チゲ 2021/2/14 22:04 ◆WZeL9z8yLqFX
参照型というと、INCのヘルプにあったあの厄介そうな処理の事を考えないといけない訳ですか…
関数とセットにするよう覚えときます
アバター
Na 2021/2/15 18:15 ◆QoELVrBXBQCI
>FORMAT関数を挟んでる時点で参照が解除されるため
重要なのそこじゃない気が。
A$[x]=... みたいに代入すると意図しないところが変わる可能性がありますが、
[x]で取り出すだけなら問題はないですよ。
C言語が分かるなら文字列をchar*として考えると理解しやすいかも

ちなみに私だったらわざわざFORMAT$なんて使わずに
ROUND(4.06*100) MOD 10 で済ませます。
あるいは (4.06*100+0.1) MOD 10 とかでもできますね。
下の桁の四捨五入を避けるために...とか一般的な解決策を求めるなら
FORMAT$で1桁多くとっても 4.0696 だと四捨五入されてしまうことに変わりありません。
20桁ぐらいとったら大丈夫か。
アバター
ツララ 2021/3/5 20:40 ◆ArUdBYOYME1V
MID$()を使うか文字列変数に[]を付けて取り出すかは可読性重視か文字数重視かで変わるかと思いますけど
後で読み直すの考えたらMID$()の方が好き。
文字列変数に[]の添え字でアクセスする方法は応用の幅が広くて、何を意図して書いてるのか分かりづらい場合ありますし。

プチコン3号で実数型のデータは倍制度実数だから
符号部分と指数部分と整数部分とに分かれてるうちの、整数部分に掛け算する
指数部分の基数が”10”じゃなくて”2”なのが、10進数表示にした時の誤差の原因になってるんじゃ無いんです?
3と4の違いって表示に必要なビット数ですし。(二進数表記だと3は"11"で、4は"100")

>Naさん
そもそものチゲさんの投稿は小数第二位の数を取り出す際に
整数部分の数によって取り出す値が変わるのはなぜ?ってことなので
計算上での四捨五入とかは全然見当違いの話なのでは。
変数に格納されてる値に直接アクセスするFORMAT$の意味分かってます?

コメントを書く

  • こちらは「プチコン3号」「プチコンBIG」など、プチコンシリーズに関する話題を扱ったコミュニティです
  • プチコンシリーズにまったく関係ない書き込みはご遠慮下さい。削除の対象となります
  • こちらにはその他のゲームや雑談のコミュニティはなく、作る予定もありません (ひとりで管理できないため)。ごめんなさい
  • ユーザー登録なしで書き込みができます
  • 秘密の合い言葉は成りすましの防止 (トリップ機能)、書き込みの編集時の本人認証に使用します
  • 秘密の合い言葉に他人に推測されやすい言葉、他サービスと同じパスワードは入力しないでください。
  • 書き込むと、投稿時に入力したお名前と秘密の暗号が記憶され、ログイン状態になります

- WEB PATIO -