bitwise operators - get single hex number (0-15) at certain position - bit-manipulation

Let's say we have hex number
x = 0x345ABC678
how can I get single hex digit (0-15) for given position >>using bitwise operators only<< ?
for example I want to get 4th number (0xA) or 6th (0xC) from hex number.
To make a long story short, I want to brute-force loop thru big database of words I converted them to 64-bit numbers (instead of strings) for example word "PUZZLER" is a number 29996611546. A is 1, Z is 33. So I want to get third letter (stored as decimal 1-33) from int 29996611546. If you could explain to me how to deal with hexadecimals I can use it in my script.
I am simple PHP programmer so I haven't had to use bitwise operators in long long time, I hope you can help me.

Steve Summit's solution/explanation is clear.
Alternatively, a 64bit number can be split into 16 hexa digits using variable bit mask. Then leading zeros can be omitted to display the meaningful digits only.
#include <iostream>
int main()
{
using namespace std;
typedef unsigned long long u64;
u64 number = 0x345ABC678;
int digits[16] = {0};
for( int i = 0; i < 16; i++ ) // fill in all 16 digits, incl. possible leading zero.
{
int shift_bits = 64 - 4 * ( i + 1 );
u64 mask = 0xFULL << shift_bits;
digits[i] = ( number & mask ) >> shift_bits;
}
int j = 0;
while( !digits[j] ){ j++; } // find the first index with non-zero digit.
cout << hex << uppercase;
cout << "digit #4 = " << hex << digits[ j + 3 ] << endl;
cout << "digit #6 = " << hex << digits[ j + 5 ] << endl;
}
Outcome:
digit #4 = A
digit #6 = C

You could start with something like
(x >> ((8 - i) * 4)) & 0xf
This numbers the digits from left to right, 1-8.
To explain how it works: Consider the example 0x45ABC678. Suppose we want the 3rd digit. We want to shift the number to the right using the >> operator, then pick off the last digit. In this case, we want to shift it to the right by 5 hex digits (which is 5*4 = 20 bits), throwing away the BC678 and leaving 0x45A. Then, when we pick off the last digit using a bitwise AND with 0xf, we get the last digit 0xA.
To get the first digit we have to shift by 7 digits. To get the third digit we have to shift by 5 digits. To get the 8th digit we have to shift by 0 digits. 8 - i gives us that pattern.

Related

Unreal Engine “FParse::HexNumber” How is it working?

(0x8877665544332211 >> 8 & 0xffff)
I am trying to convert this operation to hexadecimal, but I have not been successful.
I couldn’t use FParse::HexNumber.
https://docs.unrealengine.com/5.0/en-US/API/Runtime/Core/Misc/FParse/HexNumber64/
Has anyone tried or can help?
#include <iostream>
#include <sstream>
int main()
{
int i = (0x8877665544332211 >> 8 & 0xffff);
std::ostringstream ss;
ss << std::hex << i;
std::string result = ss.str();
std::cout << result << std::endl; // 0x3322
return 0;
}
I wrote this code in standard c++, I couldn't run it on Unreal Engine.
I don't understand how FParse::HexNumber works
Let's start with just 0x8877665544332211 >> 8. One hexadecimal digit represents 4 bits, so 8 bits is two hexadecimal digits. >> means shift right, so this much evaluates to 0x88776655443322.
That gives us: 0x88776655443322 & 0xffff. As above, one hex digit is 4 bits. 0xf means all four bits are set. So, 0xffff is 16 bits, all set. For some bit x, x & 1 = x, so this translates to keeping the 16 least significant bits of the left operand, which is: 0x3322

How do I use the char value for string?

Sorry if this is a dumb question, this is my first coding class.
If the checksum is 10, the last digit is denoted as X according to the
ISBN-10 convention. Write a program that prompts the user to enter the
first 9 digits and displays the 10-digit ISBN (including leading
zeros). Your program should read the input as an integer.
A sample run should look something like this:
Enter the first nine digits of the ISBN: 013601267
The ISBN-10 number is: 0136012671
I have successfully made a program that can do this but using int value for all nine numbers. Unfortunately, this required the user to input every number separately.
So what I am trying to do now is use use a string ISBN so that I can target individual sections ie. isbn[0] * 1 + isbn[1] * 2...
I have also tried static_cast<char>(ISBN[0]) * 1 + static_cast<char>.... thinking it would do something and I get the same results.
string ISBN;
cout << "Enter the first nine digits of the ISBN as integer: ";
cin>>ISBN;
int n10 = (ISBN[0] * 1 + ISBN[1] * 2 + ISBN[2] * 3 + ISBN[3] * 4 + ISBN[4] * 5 + ISBN[5] * 6 + ISBN[6] * 7 + ISBN[7] * 8 + ISBN[8] * 9) % 11;
if (n10 == 10)
{
cout << ISBN << "X" << endl;
}
else
{
cout << ISBN << n10 << endl;
}
So when I input this number 013601267 I should get a 1 (0136012671) at the end instead I am getting a 5 (0136012675).
I think this is happening because it is giving me ASCII dec value instead of the char value.
Four things you should check:
1: The size of the string is actually 9 characters.
if (ISBN.size() != 9) {
// Error
}
Otherwise accessing elements that do not exist will cause an error in your program.
2: The digits do not start at value 0. In ASCII (or UTF-8) the digits start at 48. Therefore 48 => '0' 49 => '1' etc. But C++ guarantees all the digits are contiguous so as long as you know the first one you can subtract that and get a correct value. If you use '0' in an integer expression it will convert to the correct value. Thus to generate a number value from a char you should subtract this value from each digit before multiplying.
n10 = ((ISBN[0] - '0') * 1) + ((ISBN[1] - '0') * 2) + ...
3: But you should check the string is all digits.
for(auto x: ISBN) {
if (!std::is_digit(x)) {
// ERROR
}
}
4: To print a string of 9 characters with leading zero you need to make sure you prep the stream coreectly:
std::cout << std::setw(9) << std::setfill('0') << number;
Or if the number is already in a string form that you know is 9 characters long you can simply use:
std::cout << ISBN;
So To output the correct 10 character number in your case:
std::cout << ISBN << ((n10 == 10) ? 'X' : ('0' + n10)) << "\n";
First you should check the size of string
if(ISBN.size() != 9){
// ERROR
}
You can use for to calculate 'n10'
int n10 = 0;
for(int i = 0; i < ISBN.size(); ++i){
if(std::is_digit(x)){ // check digit
// characters '0','1','2'... are not same as digits 0, 1, 2...
// the value of '0' is 48, as shown here [ascii table][1]
n10 = (ISBN[i] - '0') * (i+1) + n10;
} else {
// ERROR
}
}

convert hexadecimal string to binary and seperate into bits n C++

I need to covert hexadecimal string to binary then pass the bits into different variables.
For example, my input is:
std::string hex = "E136";
How do I convert the string into binary output 1110 0001 0011 0110?
After that I need to pass the bit 0 to variable A, bits 1-9 to variable B and bits 10-15 to variable C.
Thanks in advance
How do I convert the string [...]?
Start with result value of null, then for each character (starting at first, indicating most significant one) determine its value (in range of [0:15]), multiply the so far received result by 16 and add the current value to. For your given example, this will result in
(((0 * 16 + v('E')) * 16 + v('1')) * 16 + v('3')) + v('6')
There are standard library functions doing the stuff for you, such as std::strtoul:
char* end;
unsigned long value = strtoul(hex.c_str(), &end, 16);
// ^^ base!
The end pointer useful to check if you have read the entire string:
if(*char == 0)
{
// end of string reached
}
else
{
// some part of the string was left, you might consider this
// as error (could occur if e. g. "f10s12" was passed, then
// end would point to the 's')
}
If you don't care for end checking, you can just pass nullptr instead.
Don't convert back to a string afterwards, you can get the required values by masking (&) and bitshifting (>>), e. g getting bits [1-9]:
uint32_t b = value >> 1 & 0x1ffU;
Working on integrals is much more efficient than working on strings. Only when you want to print out the final result, then convert back to string (if using a std::ostream, operator<< already does the work for you...).
While playing with this sample, I realized that I gave a wrong recommendation:
std::setbase(2) does not work by standard. Ouch! (SO: Why doesn't std::setbase(2) switch to binary output?)
For conversion of numbers to string with binary digits, something else must be used. I made this small sample. Though, the separation of bits is considered as well, my main focus was on output with different bases (and IMHO worth another answer):
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
std::string bits(unsigned value, unsigned w)
{
std::string text;
for (unsigned i = 0; i < w || value; ++i) {
text += '0' + (value & 1); // bit -> character '0' or '1'
value >>= 1; // shift right one bit
}
// text is right to left -> must be reversed
std::reverse(text.begin(), text.end());
// done
return text;
}
void print(const char *name, unsigned value)
{
std::cout
<< name << ": "
// decimal output
<< std::setbase(10) << std::setw(5) << value
<< " = "
// binary output
#if 0 // OLD, WRONG:
// std::setbase(2) is not supported by standard - Ouch!
<< "0b" << std::setw(16) << std::setfill('0') << std::setbase(2) << value
#else // NEW:
<< "0b" << bits(value, 16)
#endif // 0
<< " = "
// hexadecimal output
<< "0x" << std::setw(4) << std::setfill('0') << std::setbase(16) << value
<< '\n';
}
int main()
{
std::string hex = "E136";
unsigned value = strtoul(hex.c_str(), nullptr, 16);
print("hex", value);
// bit 0 -> a
unsigned a = value & 0x0001;
// bit 1 ... 9 -> b
unsigned b = (value & 0x03FE) >> 1;
// bit 10 ... 15 -> c
unsigned c = (value & 0xFC00) >> 10;
// report
print(" a ", a);
print(" b ", b);
print(" c ", c);
// done
return 0;
}
Output:
hex: 57654 = 0b1110000100110110 = 0xe136
a : 00000 = 0b0000000000000000 = 0x0000
b : 00155 = 0b0000000010011011 = 0x009b
c : 00056 = 0b0000000000111000 = 0x0038
Live Demo on coliru
Concerning, the bit operations:
binary bitwise and operator (&) is used to set all unintended bits to 0. The second value can be understood as mask. It would be more obvious if I had used binary numbers but this is not supported in C++. Hex codes do nearly as well as a hex digit represents always the same pattern of 4 bits. (as 16 = 24) After some time of practice, you usually learn to "see" the bits in the hex code.
About the right shift (>>), I was not quite sure. OP didn't require that bits have to be moved somewhere – only that they had to be separated into distinct variables. So, these right-shift's might be obsolete.
So, this question which seemed to be trivial leaded to a surprising enlightment (for me).

C++ Changing a decimal to octal, output backwards

So I wrote this small application that will convert a decimal to octal, and it is outputting the right answer only it's backwards. An example would be that if the answer to the conversion was 17, the application would display it as 71.
Any help would be much appreciated.
;
int _tmain(int argc, _TCHAR* argv[])
{
int octal, total = 0;
cout<< "please enter a decimal: ";
cin >> octal;
while(octal > 0)
{
total = octal % 8;
octal /= 8;
cout << total;
}
cout << endl;
_getche();
return 0;
}
You can use std::oct to print number in octal notation.
int n = 123;
std::cout << std::oct << n << std::endl;
Similarly you can print number in different notations like decimal - std::dec and hexadecimal - std::hex.
Those input/output manipulators allow user to parse string numbers in various notations.
int n;
std::istringstream("24") >> std::hex >> n;
std::cout << n << std::endl; // n is 36 (decimal)
You need to take a sum and then print the final result, something like
int n=0;
while (octal > 0) {
total += (pow(10,n++))*(octal % 8);
octal /= 8;
}
cout << total << endl;
Just printing the digits will print them in reverse order since you are printing the smallest bits first.
As noted in the comments, the mechanism above will only work for converting to bases smaller than 10.
You are doing fine but you have to print the remainders in reverse order to get the correct answer . For e.g. if ans is 17 then decimal equivalent will be 1*8^1+7*8^0 . unit digit will be the remainder obtained by dividing the number by 8 , next digit to the left will be the remainder obtained by dividing the number by 8^2 and so on. So if the number in octal is of n digit then the most significant digit will be the remainder obtained by dividing the number by 8^n.That is why you have to print the remainder in reverse order.
A solution using an array for temporary storage:
int octal, total = 0, length=0;
char storage[12]; /* 11 octal digits add up to > 1 billion */
octal = 123;
while (octal > 0)
{
storage[length] = octal % 8;
octal /= 8;
length++;
}
while (--length >= 0)
printf ("%d", storage[length]);
printf ("\n");
(I happened to be in C mode, hence the printfs. Change to cout where required.)
The most important point is that you are bound by the storage size. You can set it to a reasonable size -- the largest positive octal size you can put in an integer is 017777777777 --, and even an unreasonable size is acceptable (you can set it to 20, which will only waste 8 additional bytes; these days, that's nothing). The storage size is determined by how big the representation of your number is in octal, for the largest number you can enter.
Suppose you change both 8s to 2; then you can use this same routine for binary output. But at that point, the number of output characters increases to 31! (One less than the [likely] number of bits in your int, because the last bit would toggle the number to negative. You need separate code to handle negative numbers.)
It works as-is for all bases <=10 (including "base 10" itself). If you want to extend the same code to handle bases >10, such as "duodecimal" (base 12) or hexadecimal (base 16), you need to change the printf line. This will make your code work up to base 36 ("sexatrigesimal"). Per convention, "digits" higher than 9 are written A,B,C and so on:
while (--length >= 0)
printf ("%c", storage[length] < 10 ? storage[length]+'0' : storage[length]+'A'-10);
(As I'm making this up as I write, I used the ternary operator ?..:.. for convenience, rather than a separate if..else, which needs more typing. (OTOH, adding the comment negates the gain. Oh well -- at least you learned about the ternary operator, as well as the names for a couple of number bases.))
Another solution is to use recursion. This is a useful method because it doesn't need to preallocate some space in memory -- instead, it relies on the internal call stack.
The principle is that you write a function that only prints the last digit of your number -- but before it does that, unless the remainder is 0, it calls itself with the remainder of the number.
So the function calls itself, then prints the number it should. Because it first calls itself, the called version prints the number it should -- the one to the left of the digit in the "original" function. And so on and so forth, until there is no digit remaining to be printed. From that point on, the last called function prints its number (which is the leftmost digit), returns to the function it was called from, which in turn prints its number (one more to the right), all the way down to the original call.
Recursion is a pretty cool skill to master, so do try this!
Here are two handy functions which might be useful. They return string for each of the conversions. On similar lines to igleyy's answer.
string toOctalFromDecimal (int num) {
ostringstream o;
o << std::oct << num;
return o.str();
}
string toDecimalFromOctal (int num) {
std::ostringstream o;
int x;
std::istringstream(to_string(num)) >> std::oct >> x;
o << std::dec << x;
return o.str();
}

I am not getting the answer I expect using the Bitwise NOT operator. Would appreciate some help

I am working though a C++ book trying to learn some things. I am stuck on one thing, the bitwise not. I understand it flips all the bits but it is not working how I expect in C++. Here is the relevent code.
letter = 'A'; // dec = 65 hex = 0x41 binary = 0100 0001
cout << endl << "Bitwise NOT" << endl;
cout << "Letter: " << letter << " = " << insertSpaces(toBinary(letter)) << endl;
int notletter = ~letter;
cout << "~Letter: " << notletter << endl;
string insertSpaces(string binary)
// insert spaces into a binary number string for readability
{
int pos = 4;
int len = binary.length();
while (pos < len)
{
binary.insert(pos, " ");
pos = pos + 5; // 5 because it includes space
len++; // space makes length longer
}
return binary;
}
string toBinary(int letter)
{
string result = "";
while (letter > 0)
{
result = toString(letter % 2) + result;
letter /= 2;
}
int rem = result.length() % 4;
if (rem > 0)
{
int zeros = 4 - rem;
for (int i = 0; i < zeros; i++)
result = "0" + result;
}
return result;
}
Here is the output.
Bitwise NOT
Letter: A = 0100 0001
~Letter: -66
The answer should be 190 or 1011 1110 in binary so why did I get -66?
I am using Visual C++ 2010.
Use an unsigned integer rather than a signed one. The reason you got a negative number is because most computers today use two's complement.
This is what your data looks like before and after the bitwise not:
before | after
0100 0001 | 1011 1110
(actually there's probably 32 bits there since you're using an int and not a char; the best type to use here would probably be uint8_t)
In two's complement, a number is negative if the most significant bit is 1. After the not, it is. In two's compliment, to negate a number, you take the bitwise not and add 1. If you take 1011 1110 and invert it, you get 0100 0001. Now you add one, resulting in 0100 0010. If you convert that to decimal, you get 66. Add the minus since the first bit was one, and you get -66, the unexpected value.
You are dealing with a signed number in Two's Complement. The value has exceeded the largest positive value (127) and wrapped to the negative space.
You can print it as an unsigned character/integer (i.e., (unsigned int)notletter or static_cast<unsigned int>(notletter)).