ソラマメブログ

2008年09月02日

integerデータ型と 2進法 パート2

2進数の考えを利用することで フラグを記憶することは良くあります、 コンピュータの中では(2進数:ゼロイチが走り回っているなんていいますよね^^) データや情報・記憶・計算をする方法には、ビットやバイトを計算するためのビット演算子というものがあります、これらは2個の値の各ビット同士を演算するというちょっと変わった計算をするものですね。 

セカンドライフなら リストでたくさんの要素を並べて保存しておくことができます、
記憶したり、たくさん使用することでメモリが不足することになります、(ゼロイチの数字だけでも並べて記憶するには、300個あたりでヒープエラーが発生します、16Kバイトでは500個の数字くらいがおおむね上限のようです、monoはスクリプトの動作のためにたくさんのメモリを確保することがわかっていますので、メモリ不足が発生している問題は、monoで動作実験すると良いでしょう)


2進数とビット演算を実施して、メモリ削減に役に立つ場面があるかもですね^^ 実験しましょう^^

1つの整数 =32ビットなので。(2進数で 32個の0,1)= 32個までの 0,1を記憶させることにできます。
つまり32種類の 0か1の記憶ができそうですね、 0,1を32個リストすることよりもメモリ削減できそうです、

クイズが4問あります、memory=0000(2進数) はじめはzero
右から1ビット目=1問目
2ビット目=2問目
3ビット目=3問目
4ビット目=4問目 の結果を記憶させます 0が未正解 1で正解・完成という状態を記憶するフラグを作成しましょう
4問の回答がそれぞれ、正解なのか? 不正解なのか? を記憶・保存しておけるフラグのようにできると思います。

全問正解は memory=1111(2進数) となったときです。(10進法で15ですね)
 
1問目を正解しました memory=0001(2進数)というかんじです
さらに、2問目を正解しました memory=0011(2進数)というかんじです

動作見本

数学の足し算・掛け算のように、 ビット演算子というものがあります、
普通の数字は 0123456789の文字でくみあわせた (10進法)ですが
01の文字だけをくみあわせてのが(2進法)です 

Bitwise AND &  
Bitwise OR |
Bitwise XOR ^
Left Shift  <<
Right Shift   >>
を使用しています、

1問目を正解しました ということで 1ビット目に 1を設定しましょう
temp=1<<(xx-1);  1ビット目-1で 左にシフトは ゼロしなくてもよいですね temp=0001(2進数)になります

1を設定しましょう
memory=memory|temp; これが OR演算子になります、
1ビット目に 1を設定します
他ビットは 0なら0 1なら1のままで 変化させないことができます memory=0001(2進数)というかんじです

さらに、2問目を正解しました 2ビット目に 1を設定しましょう
temp=1<<(xx-1);  2ビット目-1で 左にシフトは 1つ temp=0010(2進数)になります

1を設定しましょう
memory=memory|temp; これが OR演算子になります、
2ビット目に 1を設定します
他ビットは 0なら0 1なら1のままで 変化させないことができます memory=0011(2進数)というかんじです



//動作の実験見本 どのような数値なのか経過をSAYしてあります(10進数の数値です)
integer memory=0;
integer x;
integer data;

//Xビット目1~32に data 0or1 をセットする関数
set(integer xx, integer yy)//01~32, 0or1
{
integer temp;
temp=1<<(xx-1);
llSay(0,"temp "+(string)temp);
if (yy==1){
memory=memory|temp;
}else{
temp=temp^(0xFFFFFFFF);
memory=memory&temp;
}
llSay(0,"memory"+(string)memory);
}

//いまXXビット目 が何か? 調べる関数
check(integer xx)//Xビット目 が何か?
{
integer temp;
temp=1<<(xx-1);
temp=temp&memory;
temp=temp>>(xx-1);
llSay(0,"check ans:"+(string)temp);//0or1
}




//実験用 会話入力の方法 想定されていない入力の誤作動はチェックしていません
2桁でビット位置の整数01~32 、(カンマなど1文字を区切りに使用) セットする値(0か1だけ使用できます)
01,1     01ビット目を1 にせっと
02,1     02ビット目を1 にせっと
03,1     03ビット目を1 にせっと
04,1     04ビット目を1 にせっと
01,0     01ビット目を0 にせっと

指定するビット以外の状態はそのまま保存されて変更されないことが基本です、
初期化する場合は memory=0;ですべて 0になります。

default
{
state_entry()
{
llListen(0,"","","");
}
listen(integer channel, string name, key id, string message)
{
x=(integer)llDeleteSubString(message,2,-1);
data=(integer)llDeleteSubString(message,0,2);
llSay(0,"listen "+(string)x +(string)data);
set(x,data);
check(x);
}
}

ビット演算子については こちら参照しました
http://wiki.secondlife.com/wiki/LSL_Operators/ja

monoのwikiはここ http://wiki.secondlife.com/wiki/Mono/ja

参考・比較- - -
リスト配列に並んでいる要素の1つだけを書き換えるのは? どのように実施するのか?
入れ替えるための関数があります、ほかにも一部を削除してから、継ぎ足しをすることでも可能です、

ここ参考wiki  http://wiki.secondlife.com/wiki/LlListReplaceList

Just calling the function will not update the variable. You must store it (unless of course you are planning to act on the results straightway.)
• Bad: llListReplaceList(a, ["c"], 2, 2)
• Good: a = llListReplaceList(a, ["c"], 2, 2)

If you are storing to the same list, it can be more memory effective to clear the list before you store.
• Good: a = llListReplaceList(a, ["c"], 2, 2)
• Better: a = llListReplaceList((a = []) + a, ["c"], 2, 2)

ここにも、ヒープエラーが発生するときなど メモリが不足である場合に、(a = []) + a, としなさいとコメントがあります、、(a = []) 配列をクリア初期化することで作業エリアのメモリが開放されて、エラーが発生しないですみます。
- - - - - -


同じカテゴリー(integerデータ型)の記事
 integerデータ型と 2進法 (2008-09-01 23:05)
Posted by しんいち at 21:45│Comments(0)integerデータ型
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。