C++ 将一位换成两位
我尝试在双精度中更改一位,例如: 双x:C++ 将一位换成两位,c++,double,bit,C++,Double,Bit,我尝试在双精度中更改一位,例如: 双x:-1.500912597,即: 二进制:10111111111 000 00000011 10111100 11101101101 01100100 01001111 10010011 更改基础二进制代码中的一位(例如,位16),以便: 二进制:101111111110000000011 10111100 111011101 01100100 01001111 10010011 双x:-1.5634125969999903 有什么C++代码我可以用这个吗?
-1.500912597
,即:
二进制:10111111111 000 00000011 10111100 11101101101 01100100 01001111 10010011
更改基础二进制代码中的一位(例如,位16),以便:
二进制:101111111110000000011 10111100 111011101 01100100 01001111 10010011
双x:-1.5634125969999903
有什么C++代码我可以用这个吗?< /p> <代码>
#include <ieee754.h>
ieee754_double d = {-1.500912597};
d.ieee.mantissa1 |= 1u << 16; // set bit 16 of mantissa
double x = d.d;
ieee754_双d={-1.500912597};
d、 ieee.尾数1 |=1u唯一可移植的方法是使用
memcpy
(是的,我知道你在想什么,不,这不是低效的)
请注意,此解决方案不考虑字节顺序。你也需要考虑到这一点,以确保严格的便携性
#include <cstdlib>
#include <cstring>
#include <utility>
#include <iostream>
// only compile this function if Integer is the same size as a double
template<class Integer, std::enable_if_t<sizeof(Integer) == sizeof(double)>* = nullptr>
double or_bits(double input, Integer bits)
{
Integer copy;
// convert the double to a bit representation in the integer
std::memcpy(©, &input, sizeof(input));
// perform the bitwise op
copy |= bits;
// convert the bits back to a double
std::memcpy(&input, ©, sizeof(copy));
// return the double
return input;
}
int main()
{
double d = 1.0;
d = or_bits(d, 0x10ul);
std::cout << d << std::endl;
}
#包括
#包括
#包括
#包括
//仅当Integer与double大小相同时才编译此函数
模板
双位或_位(双输入,整数位)
{
整数拷贝;
//将双精度转换为整数中的位表示形式
std::memcpy(©,&input,sizeof(input));
//执行按位运算
复制|=位;
//将位转换回双精度
std::memcpy(&input,©,sizeof(copy));
//还双倍
返回输入;
}
int main()
{
双d=1.0;
d=或_位(d,0x10ul);
位操作有无限的可能性。所以你应该练习,但我会给你一些例子
以下代码将仅“设置”x的第3位(其中第0位为最低有效位):
以下代码将仅“重置”位3:
#define RESET_BIT3 (0xFFFFFFFFFFFFFFF7)
x &= RESET_BIT3;
你可以做的另一件事是建立这样的联盟:
typedef union
{
struct
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
unsigned BIT8:1;
unsigned BIT9:1;
unsigned BIT10:1;
unsigned BIT11:1;
unsigned BIT12:1;
unsigned BIT13:1;
unsigned BIT14:1;
unsigned BIT15:1;
};
struct
{
unsigned BYTE0:8;
unsigned BYTE1:8;
};
struct
{
unsigned ALL:16;
};
}two_bytes;
你能做的是:
two_bytes var;
var.ALL = 0; // clear all bits
var.BYTE1 = 0xFF; // make all bits of most significant byte 1
var.BIT7 = 1; // set only bit 7
或者您可以再次转换为按位运算符:
#define SET_BIT3 (0x08)
var.ALL |= SET_BIT3;
是的,有一些C++代码可以使用。你的谷歌关键词是“联合”。@标准的C++ + @ Jens bitwise运算符不能用于<代码>双 @ JoachimPileborg。可以使用<代码>无符号char */Cube >(或<代码> MeMCPy < /C>)编写该位。这并不违反严格的别名…问题是系统可能会使用各种字节顺序(如果我们假设ieee754正在使用的话)这是可能的,但您需要通过使用指针将变量视为无符号字符的数组来绕过。尽管如此,在字节顺序和实际使用的浮点格式(如@M.M所述)方面存在其他问题。这也会使代码难以理解和维护,这一点更为重要(IMO)<代码> IEEE75 4.h < /COD>不是ISO C++的一部分,最好是添加到您的答案中解释使用什么包来使用您的代码,即使IEEE75 4.h不是ISO C++的一部分,我认为访问这种方式比其他选项更干净。在Visual Studio中使用<代码> GLYBC首标包是可能的吗?我一直在尝试。要查找如何,但我说的是正确的吗?在许多平台上,代码>未签名的/CODE >是4字节宽。使用一个可移植的类型,如 UTI1616T 。标准是C++中未定义的行为。Bitfield布局是定义的实现,因此这也会使你很难知道你得到正确的字节。@ MaximEgorushkin是的,但这只是一种示例类型,有时在嵌入式平台中,我更喜欢灵活性而不是可移植性。这是制造商在其代码中定义微控制器寄存器的常用方式。据我所知,memcpy
不是唯一的可移植方式。使用char*
手动更改位也有很好的定义。我临时复制并粘贴您的代码(到VS2015中)但我有几个错误:。这是因为我使用的是另一个编译器吗?@Milan我想这是因为该系统上的无符号long
与double
的大小不同。你需要从大小中推断出正确的类型。@RichardHodges确实,在我的系统上,无符号long=4字节,而double=8字节,所以我猜不会编译函数,然后将0x10ul更改为0x10ull
two_bytes var;
var.ALL = 0; // clear all bits
var.BYTE1 = 0xFF; // make all bits of most significant byte 1
var.BIT7 = 1; // set only bit 7
#define SET_BIT3 (0x08)
var.ALL |= SET_BIT3;