【问题标题】:Converting a 'long' type into a binary String将“long”类型转换为二进制字符串
【发布时间】:2015-06-21 08:32:22
【问题描述】:

我的目标是编写一种算法,能够将长数转换为存储在字符串中的二进制数。

这是我当前的代码块:

#include <iostream>
#define LONG_SIZE 64; // size of a long type is 64 bits

using namespace std;

string b10_to_b2(long x)
{
    string binNum;
    if(x < 0) // determine if the number is negative, a number in two's complement will be neg if its' first bit is zero.
    {
            binNum = "1";
    }
    else
    {
            binNum = "0";
    }
    int i = LONG_SIZE - 1;
    while(i > 0)
    {
            i --;
            if( (x & ( 1 << i) ) == ( 1 << i) )
            {
                    binNum = binNum + "1";
            }
            else
            {
                    binNum = binNum + "0";
            }
    }
    return binNum;
}

int main()
{
    cout << b10_to_b2(10) << endl;
}

这个程序的输出是:

00000000000000000000000000000101000000000000000000000000000001010

我希望输出是:

00000000000000000000000000000000000000000000000000000000000001010

谁能找出问题所在?无论出于何种原因,该函数都会输出 10 个由 32 位表示的连接与另外 10 个由 32 位表示的连接。

【问题讨论】:

  • 为什么不直接使用std::bitset::to_string() 而不是自己滚动呢?否则,首先使用调试器来查找您的错误。另请注意,保证大小为 64 位,您需要 unsigned long long 类型。
  • 尽管声明 long 为 64 位长,但您似乎希望在输出中获得 32 位数字。可以改用sizeof吗?
  • 也许您的实现正在截断模 32 位的移位,所以当您移位 33 位时,它实际上最终会移位 1 位?尝试改用i 作为long 吗?
  • 这不会像你预期的那样编译,因为你的宏后面有一个分号。需要更多证明为什么宏是邪恶的吗?也就是说,sizeof x * CHAR_BITS 应该给你x 中的位数。
  • IIRC,移位超过位宽甚至会导致未定义的行为,@MatsPetersson。常见的实现要么将结果归零,要么以位宽为模旋转。我不确定要改变实际的位宽。

标签: c++ string binary data-conversion


【解决方案1】:

为什么你会假设 long 是 64 位? 试试const size_t LONG_SIZE=sizeof(long)*8;

检查一下,程序可以正常运行我的更改 http://ideone.com/y3OeB3

编辑:广告@Mats Petersson 指出您可以通过更改此行使其更健壮

if( (x &amp; ( 1 &lt;&lt; i) ) == ( 1 &lt;&lt; i) )

类似

if( (x &amp; ( 1UL &lt;&lt; i) ) ) 那个 UL 很重要,你可以在 cmets 中看到他的解释

【讨论】:

  • 我怀疑这不是问题所在。而不是 1 &lt;&lt; i 被执行为 1 &lt;&lt; (i % 32) - 因为我只是随机猜测 OP 正在使用 x86 系列处理器之一。
  • 也许吧,但我有疑问。 ideone.com/pkTTZX。无论如何它仍然是一个不好的做法
  • 假设你解决了这个问题,OP 的程序会工作吗?我建议您至少还需要修复班次...鉴于无论我们使用什么大小的整数,1 &lt;&lt; sizeof(T) * 8 都应该产生0 - 并且显然 OP 的代码不像那样案子。
  • 检查我所做的编辑,它有效,我 63 岁,1 &lt;&lt; (i % 32) 没有意义,你是说(1 &lt;&lt; i) % 32
  • 我的意思是1 &lt;&lt; (i % 32)——如果我的意思是别的,我会写别的——试着在你的代码中添加cout &lt;&lt; (1 &lt;&lt; 33) &lt;&lt; endl;,看看会发生什么。然后执行cout &lt;&lt; ((uint64_t)(1) &lt;&lt; 33) &lt;&lt; endl; 并找出不同之处。
【解决方案2】:

几个建议:

  1. 确保使用保证为 64 位的类型,例如 uint64_tint64_tlong long
  2. 对变量i 使用上述64 位类型以保证1 &lt;&lt; i 计算正确。这是因为移位仅在移位的位数小于或等于被移位类型中的位数时才由标准保证 - 而1int 类型,对于大多数现代平台(显然包括你的)是 32 位的。
  3. 不要在#define LONG_SIZE 的末尾加上分号 - 或者更好的是,使用const int long_size = 64;,因为这样可以实现各种更好的行为,例如,您可以在调试器中使用print long_size 并得到64,其中print LONG_SIZE 其中 LONG_SIZE 是一个宏将在调试器中产生错误。

【讨论】:

    猜你喜欢
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2020-09-11
    相关资源
    最近更新 更多