二进制按位非运算工具
对二进制数进行按位非(NOT)运算
使用工具
介绍
二进制按位非运算工具对二进制数执行按位非(取反)运算。NOT反转所有位:0变为1,1变为0。
使用方法
- 在输入框中输入一个二进制数
- 点击"计算"按钮执行按位非运算
- 查看二进制和十进制格式的结果
- 使用复制按钮复制结果
使用场景
- NOT运算:~1010 = 0101(假设4位,结果取决于位宽)
- 用于反转二进制数据中的所有位
- 应用于二进制补码表示
- 常用于位操作和逻辑运算
提示
- NOT运算:~1 = 0, ~0 = 1
- NOT是一元运算(接受一个操作数)
- 结果取决于输入的位宽
- 在二进制补码中,NOT(x) = -x - 1
二进制按位非运算工具 是什么?
二进制按位 NOT(~)计算器计算一个数的一的补码:每个比特位都被翻转(0 变 1,1 变 0)。例如,~0b00000000_00000000_00000000_00001010(十进制 10)= 0b11111111_11111111_11111111_11110101(十进制 -11,二的补码)。在 JavaScript 中,~ 通过 ToInt32 将操作数强制转换为 32 位有符号整数(截断浮点数并回绕超过 2^31 的值),结果也是 32 位有符号整数。算术恒等式 `~x = -x - 1` 成立,因为 JavaScript 使用二的补码:翻转 x 的所有比特位得到 -x - 1。常见用途:检测 -1(`if (~str.indexOf(pattern))` 在找到时为真值,因为 ~(-1) = 0 为假值),对正数进行向下取整(`~~3.7 === 3`,比 Math.floor 更快),以及通过 `& ~mask` 清除比特位(与掩码的补码进行 AND 运算可清除被掩码的比特位)。注意 `~~x` 是双重 NOT,可将浮点数截断为整数--这是 ES5 之前的技巧,现在已被 Math.trunc 取代。对于 64 位 NOT,请使用 BigInt(`~0n`)。NOT 运算是 NAND、NOR 和 XNOR 门的基础,它们分别构造为 NOT(AND)、NOT(OR)、NOT(XOR)--这些是数字逻辑中的通用门,因为任何布尔函数都可以仅用它们构建。
常见用例
索引查找测试(-1 哨兵值)
在 ES2016 的 String.prototype.includes() 之前,唯一的字符串搜索方法是 indexOf(),未找到时返回 -1。惯用法 `if (~str.indexOf(substr))` 之所以有效,是因为 ~(-1) = 0(假值),而其他任何索引都返回真值。现代代码使用 .includes() 或 !== -1,但 ~ indexOf() 仍出现在旧代码、jQuery 插件和简洁的代码高尔夫中。理解它对于阅读旧版 JavaScript 至关重要。
使用 & ~mask 清除比特位
要清除值中的特定位(将其设为 0),与掩码的补码进行 AND 运算:`value & ~mask`。例如,清除最低 4 位:`value & ~0xF`。这是用 `value | mask` 设置位的自然对应。权限撤销使用此方法:`perms & ~WRITE` 移除写权限,同时保持读和执行不变。如果没有 NOT,您需要手动构造补码掩码(例如用 0xFFFFFFF0 代替 ~0xF),这容易出错。
截断浮点数(~~ 简写)
双重 NOT `~~x` 将浮点数向零截断,对于 32 位有符号整数范围内的值等同于 Math.trunc(x)。对于正数,它与 Math.floor 一致。这是性能关键代码中常见的微优化(~~ 比较短,历史上比 Math.floor 更快)。现代 JIT 编译器使差异微不足道,因此为清晰起见应优先使用 Math.trunc。这个技巧仍出现在压缩代码和 Three.js 着色器等旧库中。
代码示例
NOT 用于 -1 检测和比特清除
~indexOf() 技巧依赖于 ~(-1) === 0(NOT 唯一的假值结果)。现代风格优先使用 .includes() 或 !== -1 以提高清晰度。比特清除模式 `value & ~mask` 是通用的:~mask 反转比特位(例如 ~0b010 = 0b...111101),与之进行 AND 运算可清除被掩码的比特位,同时保持其他位不变。这是用 `value | mask` 设置比特位的自然对应。
// Legacy idiom: indexOf returns -1 when not found, ~(-1) === 0 (falsy)
const text = 'Hello, World!';
if (~text.indexOf('World')) {
console.log('Found!'); // runs because ~7 === -8 (truthy)
}
if (~text.indexOf('Python')) {
console.log('This does NOT run'); // because ~(-1) === 0 (falsy)
}
// Modern equivalent: use .includes() or !== -1
console.log(text.includes('World')); // true (clearer)
console.log(text.indexOf('World') !== -1); // true
// Clear bits: value & ~mask
const ALL_PERMS = 0b111; // rwx
const WRITE = 0b010;
const readOnly = ALL_PERMS & ~WRITE;
console.log(readOnly.toString(2)); // "101" (read + execute, write cleared)双重 NOT 用于截断
双重 NOT `~~x` 将浮点数向零截断(与 Math.trunc 匹配,而非负数的 Math.floor:~~(-3.7) === -3,但 Math.floor(-3.7) === -4)。算术恒等式 ~x = -x - 1 源于二的补码表示:翻转 x 的所有比特位得到一的补码,在二的补码中等于 -x - 1。现代代码应为可读性优先使用 Math.trunc;~~ 在压缩输出中保留。
// ~~x is equivalent to Math.trunc(x) for 32-bit-safe values
console.log(~~3.7); // 3
console.log(~~(-3.7)); // -3 (truncates toward zero, NOT floor which would give -4)
console.log(~~0); // 0
// Math.trunc is the modern, clearer choice
console.log(Math.trunc(3.7)); // 3
console.log(Math.trunc(-3.7)); // -3
// ~x = -x - 1 (two's complement identity)
console.log(~10); // -11
console.log(~0); // -1
console.log(~(-1)); // 0
// Use this identity to compute -(x+1) without arithmetic:
const negateMinusOne = (x: number) => ~x;
console.log(negateMinusOne(5)); // -6最佳实践
- ✓为清晰起见,优先使用 Math.trunc(x) 而非 ~~x - 现代 JIT 编译器对两者的优化效果相同,而 Math.trunc 使意图对读者一目了然。
- ✓使用 `value & ~mask` 清除比特位 - 这是用 `value | mask` 设置比特位的标准对应。这对组合涵盖了所有比特操作需求。
- ✓对于 64 位 NOT 运算,请使用 BigInt(`~0n`)- JavaScript Number 的按位 NOT 会静默截断为 32 位,对超过 2^31 的值给出错误结果。
- ✓记住恒等式 ~x = -x - 1 - 这对于在一的补码和二的补码表示之间转换以及理解 NOT 的算术行为很有用。
- ✓在现代代码中,子字符串测试优先使用 String.prototype.includes() 而非 ~indexOf() - includes() 直接返回布尔值,对读者更清晰。
常见错误
- ✗对 32 位有符号整数范围外的值使用 ~~x - 它会静默回绕到 32 位,因此 ~~(2**40) 得到 0 而非 2^40。对大数的安全截断请使用 Math.trunc。
- ✗忘记 ~x = -x - 1 - 如果您期望 -x,NOT 的结果看起来"差一"。例如 ~10 = -11,而非 -10。这是二的补码算术,不是 bug。
- ✗在现代代码中不加注释地使用 ~ indexOf() - 虽然它能工作,但会困扰没见过这个惯用法的读者。请改用 .includes() 或 !== -1。
- ✗混淆 ~(按位 NOT)和 !(逻辑 NOT)- `~0 === -1`(真值!),但 `!0 === true`。单波浪号运算符翻转比特位,而非布尔值。
- ✗期望 ~x 总是负数 - 对于非负 x 确实如此(例如 ~5 = -6),但对于负 x 它是非负的(例如 ~(-6) = 5)。由于二的补码,符号会翻转。