如何使用按位运算根据另外两个字节来分配一个字节的特定位? (根据蒙版进行位混合)

2024-04-28

我有3个字节。

  • 一个字节决定了第 3 个字节的哪些位需要更改(1 表示位需要更改,0 表示不应发生更改)。
  • 第 2 个字节决定变化的位分配为 1 还是 0。
  • 第三个字节是发生变化的地方。

有没有办法使用按位运算符来实现此目的?如果是这样,怎么办?一个简单的公式或程序来实现这一点会很好(最好是用 c 语言)。

Example:

BitsToAssign:   0b01101011
ValuesToAssign: 0b01000010
ByteToAlter:    0b11110001

ExpectedResult: 0b11010010

标准的黑客行为是“根据掩码合并两个值的位 https://graphics.stanford.edu/%7Eseander/bithacks.html#MaskedMerge“ - 我将您的变量名称添加到 Sean Anderson 的 Bithacks 集合中的现有评论中。

unsigned int a;    // (ByteToAlter)    value to merge in non-masked bits
unsigned int b;    // (ValuesToAssign) value to merge in masked bits
unsigned int mask; // (BitsToAssign)   1 where bits from b should be selected; 0 where from a.

unsigned int r;    // result of (a & ~mask) | (b & mask) goes here

r = a ^ ((a ^ b) & mask); 

正如 bithack 评论所指出的,直接的方法是(a & ~mask) | (b & mask)- 清除每个输入中未保留的位,然后将它们组合在一起。

How a ^ ((a ^ b) & mask) works:

bitdiff = a^b是这些输入之间的按位差异。
它有一个1它们的不同之处,以及0它们是相同的。 (根据异或的定义)。

a ^ bitdiff会翻转每一位a这不同于b。实际上,b == a ^ bitdiff.
证明这一点的一种方法是 XOR 是结合的,所以a ^ (a^b) = (a ^ a) ^ b.
And x^x= 0,就像x-x = 0.
0 ^ x = x, so (a^a) ^ b = 0 ^ b = b.

但是如果我们将位差异屏蔽为仅设置位a到位从b在某些位置,我们已经实现了目标:根据掩码按位混合。blend = a ^ (bitdiff & mask);


的特殊情况(a & ~mask) | (b & mask)简单版

如果你的输入是这样安排的ValuesToAssign仅有任何一个1位在掩码选择的位置,您可以优化掉b & mask部分,只留下(a & ~mask) | b. (埃拉克隆的回答 https://stackoverflow.com/questions/68048922/how-to-use-bitwise-operations-to-assign-specific-bits-of-a-byte-according-to-two/68049185#68049185)。清除未选择的位,然后在新值中进行“或”操作以设置应设置的任何位。

另一个特殊情况是当ValuesToAssign == BitsToAssign,即修改只会设置位,而不会清除它们。这就是 OR 所做的,所以当然这个案例优化为a | b,无需清除位a在 O 环之前。


效率:

r = a ^ ((a ^ b) & mask);只有3个布尔运算,
与 4 相比(a & ~mask) | (b & mask)如果所有三个输入都是运行时变量。 (一个按位“非”,两个“与”,加上一个“或”)。

If mask是一个常数,然后常数传播到~mask使其成为常数,并且大多数机器可以使用至少 8 位 AND 掩码进行 AND 立即运算。所以你仍然只需要 3 条指令:两个 AND(带有逆常量)和一个 OR。

有些机器(例如带有 BMI1 的 x86)甚至有一个andn https://www.felixcloutier.com/x86/andn的指令x & ~y,允许(a & ~mask) | (b & mask)通过 3 条指令即可完成。

对于延迟,(a & ~mask) | (b & mask)有更多指令级并行性. If mask and ~mask提前准备好a and b,只有两个并行的 AND 运算和一个 OR,来自a and b输入准备好到输出准备好。在普通的超标量机器(可以在同一周期内执行两个独立的 AND 运算)上,从输入到输出只有 2 个周期的延迟。 (再次假设mask提前准备好,或者像这样的指令andn存在是为了做a & ~mask在一次操作中)。

如果关键路径经过mask(即它还没有准备好),并且你没有像这样的指令andn to do ~ and &作为一项操作,延迟来自mask to result是 3 次操作,~, &, and |。 (假设b & mask可以并行运行,而不会减慢这三个中任何一个的速度)。

延迟时间为(a & ~mask) | (b & mask)在现代 OoO 执行机器上。
(与吞吐量成本不同 https://stackoverflow.com/questions/692718/how-many-cpu-cycles-are-needed-for-each-assembly-instruction/44980899#44980899)

  • a -> 结果:2 个周期
  • b -> 结果:2 个周期
  • 掩码 -> 结果:3 个周期(或在某些机器上 2 个周期)

但位差方式没有任何ILP;这是一个由 3 个操作组成的链。a^b要求这两个输入都为第一步做好准备,然后mask需要准备好& mask步。决赛a ^ ...步骤是使用之前已经需要的输入。所以只有 3 个操作,但它们是连续的。

延迟时间为a ^ ((a ^ b) & mask)在现代 OoO 执行机器上。

  • a -> 结果:3 个周期
  • b -> 结果:3 个周期
  • 掩模 -> 结果:2 个周期

相关问答:

  • 根据掩码合并位序列a和b https://stackoverflow.com/q/39282691- 这在 SIMD 编程中称为混合。如果其他人使用我喜欢用于此操作的“位混合”术语,我不知道,但 IMO 清楚地描述了它。 x86 的 AVX-512 扩展具有 3 输入布尔运算vpternlog具有来自 8 位立即数的真值表,因此可以在一条指令中完成。

  • 在两个字节之间的给定点交换位 https://stackoverflow.com/questions/3562347/swapping-bits-at-a-given-point-between-two-bytes/50839334#50839334- 相同的 bithack 想法,但将屏蔽位差异应用于both输入以交换掩码位置处的位。

  • https://catonmat.net/low-level-bit-hacks https://catonmat.net/low-level-bit-hacks- 从对操作员的介绍开始(例如^按位异或)。包括使用 + 和 - 的位黑客(以及击中 1 或 0 的进位传播效果,例如x & (x-1)清除最右边的设置位。)

  • https://agner.org/optimize/ https://agner.org/optimize/了解有关现代 CPU 调优的更多信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用按位运算根据另外两个字节来分配一个字节的特定位? (根据蒙版进行位混合) 的相关文章

  • c++11 正则表达式比 python 慢

    嗨我想了解为什么以下代码使用正则表达式进行分割字符串分割 include
  • 如何使用 ASP.NET MVC 进行 HTTP 调用?

    我正在尝试做的事情 我试图练习进行 HTTP 调用 如果这就是它的名字 来自一个简单的 ASP NET MVC Web 应用程序 为此 我尝试从以下位置获取天气详细信息打开天气地图 http openweathermap org appid
  • 将指针转换为浮点数?

    我有一个unsigned char 通常 这指向一块数据 但在某些情况下 指针就是数据 即 铸造一个int的价值unsigned char 指针 unsigned char intData unsigned char myInteger 反
  • 使用静态类型代替变量

    当您的项目不使用命名空间时 有什么方法可以告诉编译器使用静态类型而不是变量吗 例如 我有一个名为 User 的类 它具有各种静态和非静态方法 假设调用了其中一个静态方法GetUser 我想称之为User GetUser 方法来自一个方法 该
  • 异步方法中的异常未被捕获

    下面的代码没有捕获我的OperationCancelEException 它是通过调用抛出的ct ThrowIfCancellationRequested public partial class TitleWindow Window IA
  • 基于 MS Bot Framework 中的响应分支对话框/表单

    我们正在尝试使用 MS Bot Framework 但尚未完全弄清楚如何实现此场景 我们有一个 LUIS 对话框 类型 它工作正常并且经过适当的培训 以常见的三明治为例 LUIS 意图寻找的基本内容是用户询问订单状态 如果问题中提供了订单号
  • async wait 在调用异步方法时返回 Task> 而不是 List

    我正在尝试了解 async wait 的用法 并且研究了一些博客文章 现在我已经编写了一个测试代码 但它没有按照我期望的方式工作 我有一个返回列表的方法 private List
  • 正则表达式删除某些字符周围不需要的空格

    我正在尝试从 JavaScript 文件中删除一些不需要的空格 并在将文件发送到客户端之前使用 C 和 Regex 组合文件 我有一个JavascriptHandler处理 js 文件 效果很好 这是我用来 打包 JavaScript 的函
  • 使用成员作为实现者来实现接口

    我有实现 IA 的 A 类 现在我需要创建也应该实现 IA 的类 B B 类有 A 类的实例作为成员 有什么方法可以定义A的实例实现B类中的IA吗 interfase IA void method1 void method2 void me
  • 替换 JSON 中的转义字符

    我想用空格替换 JSON 字符串中的 字符 我怎样才能做到这一点 我发现从 JSON 字符串中删除所有转义字符的最简单 最好的方法是将字符串传递到正则表达式 Unescape 方法 此方法返回一个没有转义字符的新字符串 甚至删除了 n t
  • Qt mouseReleaseEvent() 未触发?

    我有一个显示图片的库 我们称之为 PictureGLWidget 其中 class PictureGLWidget public QGLWidget 所以 PictureGLWidget 扩展了 QGLWidget 在PictureGlWi
  • C 的“char”使用什么字符集? [复制]

    这个问题在这里已经有答案了 简单的问题 我最近开始用 C 编程 有一个简单的问题 C 编程语言在其 char 类型中使用什么字符集 例如 ASCII 还是取决于软件 操作系统 char 本质上是 1 个字节 主要在所有操作系统上 所以默认情
  • 如何使用 libpq 获取双精度值?

    The examples http www postgresql org docs 9 3 interactive libpq example htmllibpq 文档中展示了如何通过将整数值转换为主机字节序表示来获取整数值 我很好奇必须做
  • Qt:将拖放委托给子级的最佳方式

    我在 QWidget 上使用拖放 我重新实现了 DragEnterEvent dragLeaveEvent dragMoveEvent 和 dropEvent 效果很好 在我的 QWidget 中 我有其他 QWidget 子级 我希望它们
  • C 中什么函数可以替换字符串中的子字符串?

    给定一个 char 字符串 我想查找所有出现的子字符串并将其替换为备用字符串 我没有看到任何简单的函数可以实现这一点
  • double 类型的静态类成员的常量表达式初始值设定项

    在 C 11 和 C 14 中 为什么我需要constexpr在下面的代码片段中 class Foo static constexpr double X 0 75 而这会产生编译器错误 class Foo static const doub
  • 使用 roslyn 扩展 C# 语法

    我试图在没有 else 情况的情况下实现 return if return value if 因为我只想在条件有效时返回或返回一个值 我知道 有if condition return or if condition return value
  • 致命错误 C1001:编译器中发生内部错误(编译器文件“msc1.cpp”,第 1325 行)

    当我编译代码时 错误指向以下类 该错误在两行上突出显示 如下所示 tm validFrom tm validUntil struct t SslCertData final struct t Contact TCHAR Organizati
  • 如何向 ItemsControl 中的 WPF 按钮添加相同的命令

    如何将命令添加到 wpf 按钮 该按钮是ItemsControl并正在修改ItemsSource itself 这是我的 XAML
  • 如何将 char 转换为 unsigned int?

    我有一个字符数组 它实际上用作字节数组 而不是用于存储文本 在数组中 有两个特定字节表示我需要存储到无符号 int 值中的数值 下面的代码解释了设置 char bytes bytes 2 bytes 0 0x0C For the sake

随机推荐

  • Dataproc:使用 PySpark 从 BigQuery 读取和写入数据时出现错误

    我正在尝试读取一些 BigQuery 数据 ID my project mydatabase mytable 原始名称受保护 来自用户管理的 Jupyter Notebook 实例 内部Dataproc https cloud google
  • 通过命令行创建私有 github 存储库

    我希望能够通过命令行创建一个私人 github 存储库 我认为使用其余 API 应该可以做到这一点 但是我无法从文档中弄清楚如何做到这一点 这可能吗 The GitHub CLI https github com cli cli tool
  • 安全浮点除法

    我的代码中有一些地方我想确保 2 个任意浮点数 32 位单精度 的除法不会溢出 目标 编译器不保证 足够明确 对 INF INF 的良好处理 并且 不完全保证 IEEE 754 的异常值 可能未定义 并且目标可能会改变 另外 我无法对这几个
  • 使用 BeautifulSoup 在 python 中抓取多个页面

    我已经设法编写代码来从第一页中抓取数据 现在我不得不在这段代码中编写一个循环来抓取接下来的 n 页 下面是代码 如果有人可以指导 帮助我编写从剩余页面中抓取数据的代码 我将不胜感激 Thanks from bs4 import Beauti
  • 为什么playsound函数无法在python中播放我的mp3文件

    所以基本上我试图创建一个音乐播放程序 可以在您要求时播放音乐 我只是想让歌曲播放部分实际工作 所以我编写了一个超级简单的代码来测试它 import playsound playsound sample mp3 This was done i
  • 在 C# 中查找并写入大于 2GB 的文件

    在 C 中 FileStream的方法 Read Write Seek 采用integer在参数中 在一个上一篇文章 https stackoverflow com questions 5654298 filestream read wri
  • Access 2003中可以制作存储过程或函数吗?

    在Access 2003中 我们可以创建存储过程或函数吗 对于 Access 2003 答案是否定的 Access 2010 确实有表触发器和存储过程 这些是真正的引擎级例程 作为行更新的结果运行 因此 导致行修改的表单或 VBA 记录集代
  • 在 Silverlight 中克隆业务对象的最佳方法是什么?

    创建 DTO 克隆的最佳方法是什么 Silverlight 中没有 ICloneable 接口或 BinaryFormatter 类 反思是唯一的方法吗 这是我们为克隆编写的代码 这适用于 Silverlight 2 和 3 Public
  • CloudWatch:计算日志文件中特定字符串的出现次数

    我有包含特定弹簧模式的日志文件 这些字符串模式在每个日志事件中频繁出现 例如
  • Python 列联表

    作为我正在编写的项目的一部分 我正在生成很多很多列联表 工作流程是 获取具有连续 浮点 行的大型数据数组 并通过分箱将其转换为离散整数值 例如 结果行的值为 0 9 将两行切片为向量 X 和 Y 并生成列联表 https en wikipe
  • 终止进程树(C for Windows)

    以前曾有人问过这个问题 但我在代码中找不到明确的答案 我打开一个进程 ProcessA PID 为 1234 此进程打开一个子进程 ProcessAB PID 5678 完成后 我终止了 ProcessA 但 ProcessAB 仍然存在
  • Zendexpressive-php错误报告

    我正在尝试 zendexpressive 这是我的config autoload zend expressive global php当我尝试向将转到操作类的路径发出请求时 它返回错误页面 但我在 apache 错误日志中看不到任何 php
  • ggplot2 中的 date_minor_breaks

    我是初学者ggplot2 我无法使用date minor breaks在 x 轴上显示季度 刻度 这是我的代码 x lt c seq 1 12 time lt c 2010Q1 2010Q2 2010Q3 2010Q4 2011Q1 201
  • SceneDelegate 和 AppDelegate 之间的区别

    在我的 SwiftUI 项目中我看到AppDelegate文件以及SceneDelegate file 它们之间有什么区别 例如在方法之间SceneDelegate scene willConnectTo options 并在AppDele
  • Inno Setup 无法导入 DLL

    我没有运气将 Delphi DLL 导入 Inno Setup Unicode 该DLL有一个简单的过程 procedure Foo stdcall begin end exports Foo 该 DLL 包含在安装程序源中 并添加到文件列
  • 仅在 Azure Web 应用程序中从 FTP 下载文件失败

    我有一个非常基本的代码 可以从 FTP 服务器下载文本文件列表 foreach var fileUri in files try var ftpRequest FtpWebRequest FtpWebRequest Create fileU
  • WSO2 API 管理器 - 在商店中显示私有 IP

    我已经安装了 API 管理器 1 6 0 并运行了 API 管理器 但问题是商店内显示的 IP 地址是服务器的私有 IP 私有IP通过VPN访问 以下是在商店中显示为 生产 和 沙箱 URL 的 URL http 192 168 6 162
  • Internet Explorer 9、10 和 11 事件构造函数不起作用

    我正在创建一个事件 因此使用 DOM Event 构造函数 new Event change 这在现代浏览器中工作正常 但是在 Internet Explorer 9 10 和 11 中 它会失败并显示 Object doesn t sup
  • Android文件上传器与服务器端php

    我几个小时以来一直在寻找解决方案 但找不到任何解决方案 基本上 我想从我的 Android 设备上传文件到 http 网站 但是 我不知道如何做到这一点 我在设备上使用java 并且我想在服务器端使用PHP 我只想上传文件 而不是在服务器上
  • 如何使用按位运算根据另外两个字节来分配一个字节的特定位? (根据蒙版进行位混合)

    我有3个字节 一个字节决定了第 3 个字节的哪些位需要更改 1 表示位需要更改 0 表示不应发生更改 第 2 个字节决定变化的位分配为 1 还是 0 第三个字节是发生变化的地方 有没有办法使用按位运算符来实现此目的 如果是这样 怎么办 一个