2017-08-01 4 views
2

背景

を切り替える、私の代わりに私がすべて保存単一int列を、使用していますブーリアンのうち、ビットワイズ演算子を使用して圧縮されています。ビット単位の圧縮ブール - 私は、データベース内の真/偽の値の数を格納し、むしろより多くの列を作るために持っている特定のもの

例:だからDBに、certs列で、Iは131011(1 + 4 +を圧縮したい

Lead Free - Yes 
Gluton Free - No 
Free Range - Yes 
Organic - Yes 

Product 1は次のように認定され8)。

私はこの情報を圧縮して抽出するためのクイックラッパー関数を書いています(intからbooleanに配列して戻す)。

問題

私はすぐにこれから値を追加および削除するための最良の方法のかわかりません。製品を私が自由範囲ではなくなるように更新したいとします。私は圧縮されたint、マイナス4を取ることができます。それは動作します。それが既にフリーレンジでなかったら何を除いて?私が一括処理をしている場合、私は、現在Free Rangeと認定されている製品から4を取り除くだけの機能が必要です。

私はそれが長すぎるifステートメントでそれを理解しましたが、それはエレガントではありません。これは動作します:

// $certs_current is the compressed int from the DB. 
// $certs_new is a new integer. 4 would mean toggle "Free Range" to true. -4 would mean toggle it to false. 

if ($certs_current & abs($certs_new)) { 
    if ($certs_new < 0) { 
     $certs_current += $certs_new; 
    } 
} else { 
    if ($certs_new > 0) { 
     $certs_current += $certs_new; 
    } 
} 

これは多くのifステートメントです。私は|演算子で遊んだが、正の数を加えるためにしか働かない。それを-4に渡すと、破損します。そして、私はnor演算子を見つけることができません。

これを行うより良い方法はありますか?

編集:私はそれを13-4を与えると、それは私を9あげる:つまり

、オペレータがあります。しかし、もし私が9-4とすれば、それは9になるでしょうか?あるいは、ちょうど134でも。私の作業ロジックに|に追加

編集2

、私は複雑さを低減してきましたし、まだそれが働いています。新しい番号が正の場合

if ($certs_new > 0) { 
    $certs_current = ($certs_current | $certs_new); 
} else { 
    if ($certs_current & abs($certs_new)) { 
     $certs_current += $certs_new; 
    } 
} 

を基本的には、言います追加する必要がある場合は、|演算子を使用して追加します。否定的な場合は、最初に削除する必要があるかどうかを確認し、削除する必要がある場合は削除します。私が改善できると思う場所はどこですか。4がすでにtrueに切り替えされていない場合にのみ(私はそれを記述するための奇妙な方法です実現)4を追加するため

|は、if文を置き換えます。

しかし、負の数では、私は可能な場合には削除したい文である入れ子のifステートメントをまだ持っています。

+1

はそう。 –

+0

私はそれを考慮しましたが、認定には自分自身に関連する情報はありません。それらは真の虚偽値です。 –

答えて

0

回答

私はそれを理解しました。 falseにブール値を切り替えるには、私たちのことを行う必要があります

  1. は(例では13~を使用して、DBからの主圧縮int型を逆にし

  2. は、新しいint型4の絶対値に追加します。 (-4ではなく)、|を使用します。

  3. ~を使用して完全なintを再度逆転させます。

だから、一つだけif文を使用して最終的なコード、:あなたは、データベース内のようなモデル化されなければならない製品と認定間の多対多の関係を持っているよう

if ($certs_new > 0) { 
    $certs = ($certs | $certs_new); 
} else { 
    $certs = ~(~$certs | abs($certs_new)); 
} 

// 13 and 4 .... 13 
// 13 and 2 .... 15 
// 13 and -4 .... 9 
// 13 and -2 .... 13 
0

あなたは圧縮された値を持っていますが、操作を行う前にそれを展開しないのはなぜですか?

$certs_temp = $certs_current 
$is_organic = $certs_temp >= 8 && $certs_temp -= 8 
$is_freerange = $certs_temp >= 4 && $certs_temp -= 4 
$is_glutenfree = $certs_temp >= 2 && $certs_temp -= 2 
$is_leadfree = $certs_temp >= 1 && $certs_temp -= 1 

変更した値で再圧縮します(実際に変更されている場合)。

実際には4つの別々のバイナリフラグを表す格納された整数で直接操作しようとすると問題が発生すると思います。 DB内の各フラグを個別に表現するか、整数として格納する必要がある場合は、変更またはロジックを適用する前にデコードします。

+0

答えをよろしくお願いします。しかし、それは名前付き変数に私を閉じ込めるでしょう。認証を追加したり、変更したりすると、変数をやり直す必要があります。私が上に追加した方法は、より無関係なので、今後も維持しやすくなります。 –

関連する問題