コミュニティアイコン プチコン 非公式コミュニティ トピック

アバター
うょリウム(元 SPDX) ◆UTOEg1c1vr.B
2020/5/4 17:25
情報交換
文字と、CHR$と、ファイルサイズと
・うょリウムがある実験をしました。

それぞれのファイルには
1行目に
「CHR$(n)×100000」が格納されています。
n=ファイルの名前の数値です。
どのファイルも、文字数は100000ですが、サイズが最大で3倍も違います。

どうやら、

CHR$( 0〜 127)=1
CHR$(128〜2047)=2
CHR$(2048〜  )=3
と文字によってサイズが違うようですね。

この実験を初めにプチコンの「文字」に興味をもったうょリウムは、
情報の発信、収集のため、トピックを開くことにしました。

コメント

アバター
うょリウム(元 SPDX) 2020/5/4 17:41 ◆UTOEg1c1vr.B
事の発端は、
うょリウムが製作中の
「エルカミツRPG」
のストーリー案などをメモしていたファイルの容量を見て
「えっ、こんなに大きいの?」
と思ったことに始まります。

英数字(ABC123とか)より
文字(アイウエオとか)の方が容量が
大きいと仮説を立てたうょリウムは
実験を行い、
”あ”×100000 よりも
”A”×100000 の方が
サイズが小さいことを発見しました。

その実験を発展させ、
キリの良い数(64、128、256とか)
を突いていくうちに
サイズの境目を発見しました。

ではどういった文字が該当するのだろう、と文字を片っ端からプログラムに書き出し、実用的な文字をリストアップしました。
どうやら漢字以外でもキーボードにない文字は多数あるようですね。
EDITモードの左側にあるアレも文字として存在していたことも分かりました。

CHR$(POW(2,30)-1)まで表示できることを確認しましたが、
どうやら65536ごとにループしているらしいです。
※ASC(CHR(65536))=0です。

コンソールでは映らないけど
DIALOGだと出る文字なんかは
ごく一部で、ほとんどは存在しない
文字なんですね。
パソコンだと出る文字なのかなぁ…
アバター
こういち 2020/5/4 18:05 ◆ou0jbJnEJ0Kb
マルチバイト文字ってやつか…
その辺ははるくんが詳しかった気がする。
結局1バイト(8ビット)にはどう足掻いても256文字しか入らなくて、うち1ビットは元々誤り検出とかに用いられてたのよね。
ここからは想像だけど、UTF-8とかUTF-16とかでは最上位ビットがマルチバイトかそうでないかを区別する役割を持ってると思う。(だから128以上だと2バイトになる)
聞いたことある話だと、マルチバイト文字は国によって違うとか?(うろ覚え)
アバター
あまさとしおん 2020/5/4 18:18 ◆mzDKTVUAtwqE
実際、上の数bitを確かめることで、1文字が何バイトに分けられるかどうかを識別できるんだよね(wikipediaをかじりながら)
アバター
高原のな 2020/5/4 18:22 ◆bY8RViwvoODw
UTF-8は、文字コードの値に必要なビット数に合わせて1文字分のコード長を伸ばすのです
その数値範囲が8ビット分(256、65536など)とかみ合わないのですが、これは1文字のコード長を分類するためにマークみたいなのをつけているからです
詳しい形態はググれば出てくるということで忘れちゃいましたが

いろいろ試したけれどプチコンでは65536でループしますね、𠮷野家(機種依存文字を使用。吉の上が土の形)と表示しようと試みたことがありましたが無理でした()
アバター
あまさとしおん 2020/5/4 18:27 ◆mzDKTVUAtwqE
65536でループする(0-65535番までしか使えない)ということを専門的に表現したのが「BMP(基本多言語面)のみ」ということです
プチコン4公式サイトの基本仕様にはちゃんと書いてあるのですが、3号だと「BMPのみ」の但し書きが書いていないのが不親切ですね…
アバター
あまさとしおん 2020/5/4 18:35 ◆mzDKTVUAtwqE
UnicodeとUTF-8/UTF-16の違いの「大まかな違い」ですが
Unicodeは「文字ごとの番号を決めるルール」で
UTF-8/UTF-16は「文字ごとに決まった番号を、バイナリにするときの変換ルール」

UTF-8とUTF-16はバイナリが全然違う物になりますが、文字ごとの番号は一緒なので、機械的な規則で変換することができます。
アバター
高原のな 2020/5/4 18:37 ◆bY8RViwvoODw
UnicodeにおいてBMPってそういう意味だったのか

ところでBMPしか使えないのであれば、日本語が主体になるようなファイルは整数配列を使って、一要素32 bitの上下の順を決めて16 bitずつ収めていけば多少ファイルサイズが小さくなるのかも?(ややこしい処理が増えそうですが)
アバター
あまさとしおん 2020/5/4 18:43 ◆mzDKTVUAtwqE
実際に、日本語テキストは整数型のDATファイルに詰め込んだ方が小さいです
SDカード容量の限り保存できるプチコン3号だと、シビアになる必要は無いですが、DLにかかる時間を減らせる点でユーザーにやさしいのです

その目的だと、普通にDeflate圧縮ツールで良いのでは感がありますが、解凍が高速というメリットがあります(FOR-NEXTとCHR$()とビット演算ぐらいしか処理が無いので)
アバター
はる 2020/5/4 21:10 ◆75Vh4SY8TdKS
プチコンでは表面上はUTF-16として扱われますが、
保存時にはUTF-8に変換されて保存されるというのは、
殆ど使うことのないUTF-8における2byte文字の存在含めて、
過去にも何度か話題になった記憶があります。
UTF-8が文字によってサイズが違うことを実感することは、
プチコンに限らずよくあります。(自分の掲示板のように容量制限があるとこなど)
UTF-8における3byte文字ばかりの文字列を格納する際には、
高原のなさんとあまさとしおんさんの方法で、
UTF-16のまま詰め込んだ方がいいかもしれませんね。

CHR$()がBMP外にコードポイントを指定しても出てこないというのは、
今まで話題にも上がっていないような気がしますが、
自分も昔試してループしている?と気づいたことがあります。
多分下位2byteだけを読み取っているのだと思います。
(MMLが下位1byteだけだったみたいに)
BMP外は完全に非対応っぽいです。
確かサロゲートペアとか使っても無理だった気がします。
というかWii Uやニンテンドー3DSはOS全体で非対応のようです。
Nintendo SwitchはOSレベルでは対応しているようだけど4でも使えないようですが。


こういちさん

確かに自分はUnicodeとかは好きなので平均よりは詳しいかもしれません。
「マルチバイト文字は国によって違う」というのはよく分かりませんね。
国によって色々な文字符号化方式が使われているので、
文字符号化方式によってシングルバイト文字とマルチバイト文字が違う、
ということですかね。
Unicodeのような国際的に通じる符号化文字集合が広く浸透していて、
実際、UTF-8などの文字符号化方式を使うサイトを多く見ます。
なので最近はあまり国によって違うみたいなのは聞かないですね。
Windowsで多く使われたりこのサイトでも使われているShift_JISは、
日本語に特化した文字符号化方式ですが。
それでも確か日本語の文字がマルチバイト文字だったような気がします。
ASCII文字と半角カナがシングルバイト文字で。
まあUTF-8とかだと思いっきり半角カナはマルチバイト文字だったりするので、
Shift_JISがこれに当てはまらないとは言い切れないかもしれませんね。
アバター
うょリウム(元 SPDX) 2020/5/4 22:07 ◆UTOEg1c1vr.B
案の定。
難しいお話がわいてきましたね。

しかし文字の話題を語るには無知すぎたのですが、
あれから
UTF-16の文字コードを調べてCHR$(&H****文字コード)と入力すればその文字を表示できるということは理解できました。
DIALOGでしか出せない文字も多いようですが…。

2Bの文字は、エルカミツRPGでよく使っています。
ì í î ù ú ò ó ôÌ Í ÎÒÓÔ σ 辺りを
コンソールで目や鼻+口として使います。

■■■
▼▼▼
î  î
 ù   <さすが皆さん詳しいですー
▲■▲   ◇
■■■■■◆
■■■
□□□
□ □
□ □
▲ ▲
アバター
うょリウム(元 SPDX) 2020/5/4 23:09 ◆UTOEg1c1vr.B
文字の話題が中心になってるが、
じつはファイルサイズが
実験のメインテーマなんですよねー。

あ、ちなみにSAVE”TXT…の説明に
UTF-8と書いてありました。

ファイルサイズについて

プログラム 
1文字につき1〜3バイト
1行につき1バイト
1行目”A”×100だと101バイト
1行目”あ”×100だと301バイト

文字列(TXTファイル)
1文字につき1〜3バイト
”A”×100だと100バイト
”あ”×100だと300バイト
””だと1バイト

数値配列(DATファイル)
28バイト+要素1つにつき8バイト。
要素数が1つなら36バイト。
要素数が100なら828バイト。
10000要素なら82008バイト。
数値の中身は0でもPOW(2,1023)でも変わらない。

GRPファイルのサイズは
524316で固定ですが、
これはドット数(512×512)
×2+28の数値となります。
1ドットが2バイトで収まっているのですね。
28というのは
数値配列の基本サイズと同じですね。
配列と共通点があるのでしょうか。

新たなどうでもいい実験
POW(2,1024)でinfになる。
POW(2,1024)/POW(2,1024)で
nanになる。
POW(2,1023)/POW(2,1023)では
1になる。

数値は100桁直接入力するとエラーになるようです。そもそも途中から正しく表示されなくなりますが。
また無知なのに語ってしまいました。
アバター
高原のな 2020/5/5 5:48 ◆bY8RViwvoODw
(9:21追記 頭が回ってなくて多数計算ミスをしてました。16桁の話以外は直せたと思います)

DATファイルとGRPファイルはどうやら28バイトでなにかしらのメタデータを保持しているようですね。
なお、プチコンの数値配列には整数型配列と実数型配列があり、1要素のサイズが前者は4バイト、後者が8バイトです。DIM A%[]とすると整数配列になるので、そちらも一度試してみてはいかがでしょう。


数値に関して、実数型(以下64ビット浮動小数型と呼びます)は指数を用いた形式でして、雑に書き表すと「符号×仮数部×POW(2,指数部)」という形式です(実際はもう少し複雑ですが)。

(Wikipediaで確認しながら)標準規格に沿うと、64ビット浮動小数型は仮数部52ビット、指数部11ビット、符号1ビットをとるそうですね。
仮数部は「ケチ表現」によって52ビットでありながら53ビット相当の情報を持ちます。1ビット分表現に使うビットをケチれるのでケチ表現。
指数部は、0埋め(ビット表現上の0)と1埋め(ビット表現上の2047(10進法))は特別な意味を持ち、さらに数値の読み替え(バイアス)によって、ビット表現上の1023(10進法)が指数部0を指します。
これより、ビット表現上の2046(10進法)が指数として意味を持つ最大値で、このとき指数部は1023(10進法)となります。
以上の情報をまとめつつ細かい計算の中身を端折って説明すると、表せる最大値は「POW(2,1024)よりちょっと小さい数」(といっても2^1024との差は2の(だいたい)970乗という大きい数です)になります。
これを超えるとinf扱いになるっぽいですし、infが絡む特定の計算はNaN(Not a Number)になります(不定形など)。

(また、64ビット浮動小数は10進法約16桁の精度を持つといわれています。これが意味するところをどう説明できるかは、後にさせてください)

ここまで書いて、細かいことを確かめるためにググって気づいたのですが、このあたりのことは、まとめWikiにまとめてありました……(ググったら上位に出てきた)
http://wiki.hosiken.jp/petc3gou/?Mame%2FMathInfNan
アバター
CyberRex 2020/5/5 7:13 ◆qhyT2aHAyMJC
確かファイルヘッダーは100バイトあったような気がしましたけど…。
アバター
はる 2020/5/5 8:15 ◆75Vh4SY8TdKS
プログラムが1byte増えているのは改行のせいでは。
改行をクリップボードに入れて置換ツールにコピペして、
改行を置換してしまえば1byte分節約できる裏技があります。

DATファイルおよびGRPファイルには、
それぞれのファイルにつくヘッダ(容量としてカウントされない)とは別に、
DATファイル用のヘッダ(容量としてカウントされる)が付与されるようです。
元々、海外勢が内部データの解析で見つけたものです。
http://smilebasicsource.com/page?pid=652
その後、Miiverseのプチコン3号 SmileBASIC コミュニティで、
EXEC命令の引数にDATファイルのファイル名を書くことで、
DATファイルをTXTとして読み込めてしまうバグが発見された時に、
TXTとして読み込んだDATファイル内にヘッダがあることが話題になり、
TXTとして読み込めることを利用してヘッダを解析し、
DATファイルの情報を表示するプログラムが作られたりしました。
http://wiki.hosiken.jp/petc3gou/?Toukou%2FDAT%A5%D5%A5%A1%A5%A4%A5%EB%A4%CE%A5%D8%A5%C3%A5%C0%B3%CE%C7%A7%A5%C6%A5%B9%A5%C8
しばらくした後、そのバグは修正されてしまったようですが。

後、GRPファイルは内部的にはDATファイルなので、
ちゃんとGRPファイルのフォーマットに従っていれば、
DATファイルとしてGRPファイルをLOADしたり、
DATファイルとしてGRPファイルをSAVEしたりできます。
DATファイルとしてGRPファイルを保存すると、
512×512以外のサイズで保存できたりするので便利です。
アバター
うょリウム(元 SPDX) 2020/5/5 10:00 ◆UTOEg1c1vr.B
ちょっと待った。
GRPファイルを512×512以外で保存できるなんて便利なんてもんじゃないでしょう!
そんなの画期的すぎるじゃないですか!?
と、いうか初耳だ。
知らんよ。そんなん。

改行を置換できるのも知らなかった…
無知な私を笑うがよい。フハハハハ!

高原のなさんの説明でまぁ何となく理解できました。
倍精度実数ってなんじゃそりゃって思ってたのですが最近の色々で
少しだけ理解できました。
裏でデータ節約のために色々あるんですね。

整数にすると節約できるんですね。
では今度からDATファイルに保存する時ぐらいは整数も使ってみます。
(今までは%がついた変数を見ると頭が混乱するので使ったことがないし、
意識から飛んでいた。)
↑使わないから混乱するのである。

ところで1バイトって
8ケタの2進数でしたね。
256通りですよね。

 256
× 256
-------
1536
12500
512
-------
65536
 

32×32×32=16184通りの色コードを格納するのに2ビット余るんですね。
GRPファイルの大きさを思うと
これがもったいないような気がしてしまう…。
アバター
Na 2020/5/5 10:10 ◆QoELVrBXBQCI
この前512x512ではない長方形サイズのDATをGRPとして読み込んだんですが、どうも縦と横の要素数が逆に認識されてしまう? みたいなバグがあるみたいです。
たぶん1次元配列に入れてGLOADの方が確実です。
http://petitverse.hosiken.jp/community/petitcom/topic/?read=1314&ukey=0

ちなみにプログラムの最初に OPTION DEFINT と書くとそのプログラムのすべての変数が%を書かなくても自動的に整数型になります。
アバター
こういち 2020/5/5 10:13 ◆ou0jbJnEJ0Kb
ッ透明度
アバター
高原のな 2020/5/5 10:16 ◆bY8RViwvoODw
あれ、32^3=32768で、15 bitではないですか?
このとき、残りの1 bitは透明度情報のために使われています。こいつが0なら何でも透明です。内部的には色付きの無色透明というわけわからんデータになってます。
プチコン3号/BIGでは無色透明しか表せないので色部分が無駄データな感じがしますが、4では透明度も(他の色情報も)8 bitになったので、色付き半透明が表現できますね

整数にすると、ビット演算を駆使すればデータをかなり詰め込むことができますから、ちょっぴりうれしくなります(

(どうでもいいですが、普段わたしはあまり実数を扱わずにプログラムを書いているので、OPTION DEFINTがデフォです)
アバター
うょリウム(元 SPDX) 2020/5/5 17:03 ◆UTOEg1c1vr.B
ああ、15ビットでしたか。
普通に計算ミスですね。

コメントを書く

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

- WEB PATIO -