[解決済み】ビット単位のLess than or Equal to
質問内容
コンテストのためという誤解があるようです。 私はある課題を解決しようとしているのですが、もう1時間もこの問題で行き詰まっています。
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
int greater = (x + (~y + 1))>>31 & 1;
return !(greater)|(!(x^y));
}
コメントで指示されているように、ビット演算子しか使えないのですが。
を解く方法がわかりません。
x <= y
;
私の思考回路では、x をその 2 の補数として設定することができます (
~x +1
で追加します。
Y
. マイナスの場合は
X
よりも大きい。
Y
. したがって、それを否定することによって、私は逆の効果を得ることができます。
同様に、私は以下のことを知っています。
!(x^y)
は、次のものと同等です。
x==y
.
しかし
して
!(greater)|(!(x^y))
は適切な値を返しません。
私はどこで混乱しているのでしょうか?ちょっとしたロジックが抜けているような気がするのですが。
解決方法は?
もし
x > y
であれば
y - x
または
(y + (~x + 1))
は負の値なので、上位ビットは1になり、そうでなければ0になります。
x <= y
これの否定である。
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
return !(((y + (~x + 1)) >> 31) & 1);
}
さらに良いのは、シフト演算子をやめて、ハイビットにビットマスクを使用することです。
int isLessOrEqual(int x, int y)
{
return !((y + (~x + 1)) & 0x80000000);
}
EDITです。
コメントで指摘されたように、上記のバージョンは算術オーバーフローエラーに弱いです。エッジケースをカバーする別バージョンを紹介します。
#include <limits>
int isLessOrEqual(int x, int y)
{
static int const vm = std::numeric_limits<int>::max();
static int const sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
説明:全体的な戦略は、入力の符号ビットを残りのビット("値ビット)とは論理的に異なるものとして扱い、前の例と同様に値ビットだけに対して減算を実行することである。この場合、2つの入力が両方とも負または両方とも非負である場合にのみ減算を実行すればよい。これにより、算術オーバーフローを回避することができます。
のサイズが小さいので
int
厳密には実行時に不明なので
std::numeric_limits<int>::max()
を値ビットの便利なマスクとして使用します。符号ビットのマスクは,単に値ビットのビット単位の否定である。
の実際の表現に目を向けると
<=
を分解すると、ビット単位のマスク
sm
の符号ビットの演算を行い、式の外側に押し出す。論理式の第1項
x & ~y
が真であるとき
x
が負で
y
は非負である。次の項の第1因子
~(x ^ Y)
は両方が負のとき、または両方が非負のときに真となる。第二因子
~((y & vm) + ~(x & vm) + 1))
が真である場合
y - x
は非負であり、言い換えれば
x <= y
,
符号ビットを無視する
. この2つの項は、orがつくので、c++の論理式構文を使うと、次のようになります。
x < 0 && y >= 0 || (x < 0 && y < 0 || x >= 0 && y >= 0) && y - x >= 0
は
!!
一番外側の演算子で、上げた符号ビットを
1
. 最後に、Modern C++のテンプレートである
constexpr
のバージョンです。
template<typename T>
constexpr T isLessOrEqual(T x, T y)
{
using namespace std;
// compile time check that type T makes sense for this function
static_assert(is_integral<T>::value && is_signed<T>::value, "isLessOrEqual requires signed integral params");
T vm = numeric_limits<T>::max();
T sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
関連
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み】ビットシフト(bit-shift)演算子とは、どのようなもので、どのように機能するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】識別子 "string "は未定義?
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。