- ベストアンサー
C言語のビット演算をPHPで実装する方法
- C言語のビット演算をPHPで実装する方法を教えてください。
- 具体的には、bitを左シフトしている箇所と - 0x30の箇所をどのように書けば良いのかわかりません。
- また、Value[i]の配列内には整数が1桁ずつ格納されています。この配列からビット演算を行い、最終的な結果を求めたいです。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
function MakeScramble($nVers, $nScramble, &$Value) { $Cnt1 = $Cnt2 = $Cnt3 = 0; $c = array_values(unpack('C*', $Value)); for ($i=0, $j=1; $i<=28; $i++) { if ($i==4 || $i==9 || $i==18 || $i==21 || $i==28) { $j ++; continue; } $Cnt1 += bit_count_as_byte($c[$i] & 0xAA); if ( $j == 2 || $j == 5 ) { $Cnt2 += bit_count_as_byte($c[$i]); } if( (10<=$i && $i<=13) || $j == 4 || $j == 5 ) { $Cnt3 += $c[$i] - 0x30; } } return $Value .= sprintf('%d%d%04d', $nVers, $nScramble, (($Cnt1 + $Cnt2)*2) + $Cnt3); } function bit_count_as_byte($byte) { $byte = ($byte & 0x55) + (($byte >> 1) & 0x55); $byte = ($byte & 0x33) + (($byte >> 2) & 0x33); return ($byte + ($byte >> 4)) & 0xF; } ============================================================================= $Value = 'C01R-0021-20101119-01-011456-'; MakeScramble(1, 1, $Value); var_dump($Value); これで、同じ動作になっていると思います。 PHP で文字コードを取り出す場合は ord や unpack などがありますので、それらを通してやれば、後は C と同じです。 注意点としては、数値文字列に対する関数も多く用意されているので、それらと混同しないように気をつけてください。
その他の回答 (7)
- yuu_x
- ベストアンサー率52% (106/202)
補足 pdf の説明と C のプログラムに食い違いがありましたので、C のプログラムにあわせて書いてありますが、pdf の説明に合わせる場合は、 if( (10<=$i && $i<=13) || $j == 4 || $j == 5 ) { $Cnt3 += $c[$i] - 0x30; } の部分を if( $j == 3 || $j == 4 || $j == 5 ) { $Cnt3 += $c[$i] - 0x30; } としてください。
- yuu_x
- ベストアンサー率52% (106/202)
> 掲載いたしましたが実際にはValue[0]とValue[3]はアルファベットが入っています。 なんとなくそんな気はしてたんですが、配列の値が整数ではなく数字文字ということはないですか? もし、そうだとするなら、$Value を $Value = array_map( 'ord', array (1, 0, 1, 1, 2, 0, 0, 2, 1, 8, 2, 0, 0, 9, 1, 2, 1, 1, 4, 0, 1, 3, 1, 0, 4) ); // 念のため、他の部分も $Cnt1 = $Cnt2 = 0; for ($i=0; $i<=24; $i++) { for($j=0,$bit=1; $j<8; $j++,$bit<<=1) { if($Value[$i] & $bit) { if(($j%2)==1) { $Cnt1 ++; } } } $Cnt2 += ($Value[$i] - 0x30); } $Ans = $Cnt1 + $Cnt2; としてみてください。 0xD0 は見当違いだったようなので - 0x30 の部分はそのままにしてください。 何のプログラムか分からないので、または外してるかもしれないけど。 差し障りなければ、質問文にある配列で実行したときの Ans を教えてもらえると考えやすかったりします。
補足
ありがとうございます。 結果の値は違っていましたがかなり違いです!! あともう少しな感じがしてきました。 でもやはりもっとソースコードをお見せしないと ご相談もうまくできないので下記のURLにソースと 求めたい結果の値を掲載いたしました。 重要な部分は除いてありますが、お伝えしたいことは これでほぼ分かると思います。 http://sample.flop.jp/sample.pdf お手数をおかけいたしますが こちらを見ていただけると幸いです。
- t140
- ベストアンサー率39% (59/150)
なるほどValueってのはchar型なんですね。 これだとどうですか? $Value = array(1, 0, 1, 1, 2, 0, 0, 2, 1, 8, 2,0,0,9,1,2,1,1,4,0,1,3,1,0,4); $Cnt1 = $Cnt2 = 0; for($i=0; $i<=24; $i++) { for($j=0,$bit=1; $j<8; $j++,$bit<<=1) { if(ord($Value[$i]) & $bit) { if(($j%2)==1) { $Cnt1++; } } } $Cnt2 += $Value[$i]; } $Ans = $Cnt1 + $Cnt2; echo $Ans;
お礼
何とか解決しました! t140さん、一緒に考えてくださりありがとうございました。
補足
ありがとうございます。 しかし値がだいぶ大きくなり違うようです・・・。 やはりもっとソースコードをお見せしないと ご相談もうまくできないので下記のURLにソースと 求めたい結果の値を掲載いたしました。 重要な部分は除いてありますが、お伝えしたいことは これでほぼ分かると思います。 http://sample.flop.jp/sample.pdf お手数をおかけいたしますが こちらを見ていただけると幸いです。
- yuu_x
- ベストアンサー率52% (106/202)
$Value[$i] - 0x30 を $Value[$i] + 0xDO でやったらどうなりますか?
補足
回答ありがとうございます! $Value[$i] + 0xD0 でやってみたのですが 結果の値がやはり異なるようです。 C言語でのプログラムの方は例として結果が146だとすると PHPでのプログラムの方は(+ 0xD0の場合)812になります。 質問には例としてValue[i]の中には0から9までの整数が入るとして 掲載いたしましたが実際にはValue[0]とValue[3]はアルファベットが入っています。 それも関係ありますでしょうか?
- t140
- ベストアンサー率39% (59/150)
$cnt2 += ($Value[$i] - 0x30); これでいいと思いますが、結果どんな感じでしょうか?
補足
回答ありがとうございます! $cnt2 += ($Value[$i] - 0x30); でやってみたのですが C言語でのプログラムの結果とまったく異なる値が返ってきてしまいます。 計算の経過をechoで取ってみたのですが $Valueが0のとき - 0x30 することで -48 になり $Valueが1のとき - 0x30 することで -47 になり 結果 大きなマイナス数値が返ってきます。 C言語の方はプラスの整数になります。 ソースを公開できないためうまく説明できずすみません。 C言語のプログラムを作成した人にもコンタクトを取って相談してみます。 その結果をまたご連絡させていただきます。
- t140
- ベストアンサー率39% (59/150)
宣言部分のソースが載ってないので初期値がわからないのと結果が何になるかがわからないですが、 まずbit<<=1と代入してあるので$bit<<1ではなく$bit<<=1としましょう。 0x30はただ単に整数定数の16進表現を引いているだけなのでそのままでいいと思います。
補足
すみません、ソースをすべて公開することができず 抜粋にて掲載させていただきました。 分かりづらくすみません! 「0x30はただ単に整数定数の16進表現を引いているだけなのでそのままでいい」 というのは、下記のコードのように何もしなくていいということなのでしょうか? $cnt2 += $Value[$i]; それともPHPでも同様に下記のように書くということなのでしょうか? $cnt2 += ($Value[$i] - 0x30); よろしくお願いいたします。
- yambejp
- ベストアンサー率51% (3827/7415)
まずはこちら
補足
回答ありがとうございます! 教えていただいたページを見ながら自分なりにコードを書いてみたのですが C言語での結果の値と異なってくるのでやっぱり違うみたいです。 下記のコードが自分なりにPHPに書き直してみたコードなのですが どのように違うのか教えていただけるとうれしいです。 それとも全く違うのか・・・。 何となくデータ型に問題があるような気がするのですがどうなんでしょう? ご教授よろしくお願いいたします。 【PHP】 for($i=0; $i<=24; $i++) { for($j=0,$bit=1; $j<8; $j++,$bit<<1) { if($Value[$i] & $bit) { if(($j%2) == 1) { $cnt1 ++; } } } $cnt2 += hexdec($Value[$i]); } $ans = $cnt1 + $cnt2;
お礼
yuu_xさん、ありがとうございます!! Cとまったく同じ値が出るようになりました! これでずっと何日も悩んでいたので本当に感謝です。 すでに納期がかなり迫ってきていたので 涙が出そうなくらいうれしいです。 明日から残りの開発に邁進できそうです。 本当にありがとうございました!