I wonder how to reverse something like this. So having a mask where auto mask = 1ULL << 20; how to get 20 out from mask?
Loop-free
Many years ago when I was writing a bit-wise arithmetic for a chess engine, I found a fast implementation which is useful for your requirement, it's loop-free. This method will return the position of the first 1-bit from right-to-left (Least Significant Bit):
inline unsigned int lsb(unsigned long long value)
{
if (!value)
return -1;
value &= -value;
unsigned int lsb = (unsigned) value | (unsigned) (value >> 32);
return (((((((((((unsigned) (value >> 32) != 0) << 1)
+ ((lsb & 0xffff0000) != 0)) << 1)
+ ((lsb & 0xff00ff00) != 0)) << 1)
+ ((lsb & 0xf0f0f0f0) != 0)) << 1)
+ ((lsb & 0xcccccccc) != 0)) << 1)
+ ((lsb & 0xaaaaaaaa) != 0);
}
int main()
{
unsigned long long x = 1ULL<<20;
cout << lsb(x) << endl;
}
Output
20
I think, I had found it here.
Using log:
#include <iostream>
#include <cmath>
int main() {
auto mask = 1ULL << 20;
std::cout << log2(mask) << std::endl;
// edit out: std::cout << log(mask) / log(2) << std::endl;
return 0;
}
or loop and shift:
#include <iostream>
int main() {
auto mask = 1ULL << 20;
for (unsigned int c = 0; c < sizeof(mask) * 8 && mask; c++) {
mask >>= 1;
if (mask == 0)
std::cout << c << std::endl;
}
return 0;
}
If it's a 64-bit mask, you can compute it modulo 67 and do a table lookup.
To wit:
static int table[67] = {
-1, 0, 1,39, 2,15,40,23, 3,12,
16,59,41,19,24,54, 4,-1,13,10,
17,62,60,28,42,30,20,51,25,44,
55,47, 5,32,-1,38,14,22,11,58,
18,53,63, 9,61,27,29,50,43,46,
31,37,21,57,52, 8,26,49,45,36,
56, 7,48,35, 6,34,33};
int unmask(unsigned long long ull) {
return table[ull % 67];
}
//first if you want to make sure only 1 bit is "on" you can do that:
if ((mask & mask-1) != 0)
{
//you have more than 1 bit "on", deal with it...
}
//finding which bit is "on" can be achieve in a loop
int count 0;
while (mask > 1)
{
mask>>=1;
count++;
}
//At this point count will have the required value (20 in your example)
Option 1: iterate
while (mask && !(mask & 1)) { mask>>=1; count++; }
Option 2: iterate multiple bits at a time:
unsigned long long a=0xFFFFFFFFULL; int b=32;
while (mask>1) {
if (!(mask & a)) { count+=b; mask>>=b; }
b>>=1; mask>>=b;
}
Option 3: Convert the mask to double or float and extract the exponent.
union {
struct {
int mantissa:23;
int exp:7;
int sign:1;
} s;
float f;
} u = { (float) mask };
return u.s.exp + 1;
A simple loop will be quite okay:
for (int bit = 0; bit < sizeof(mask) * 8; bit++)
{
if ((1ULL << bit) & mask)
std::cout << "Bit " << bit << " is set in the mask\n";
}
How about a TMP solution:
#include <iostream>
template < unsigned long long MASK >
struct MaskIndex
{
enum { i = MaskIndex < MASK / 2 >::i + 1 };
};
template <>
struct MaskIndex < 1 >
{
enum { i = 0 };
};
int main()
{
const unsigned long long mask = 1ULL << 20;
std::cout << MaskIndex < mask >::i << std::endl;
return ( 0 );
}
You can try this..
if((1ULL<<20)&mask) {
cout << "20th bit is set";
}
Related
My goal is to figure out whether each element of an array is a prime or not.
Example:
Input: int A[5]={1,2,3,4,5}
Output: bool P[5]={0,1,1,0,1}
The problem is the array size is up to 10^6. I tried the most efficient prime-checking algorithm
(code: http://cpp.sh/9ewxa) but just the "cin" and "prime_checking" take really long time. How should I solve this problem, Thanks.
Your "most efficient" prime test is actually horribly inefficient. Something like the Miller-Rabin primality test is much faster on a one by one basis. If your input are below 4.3 billion (i.e. uint32_t) then you only need to do 3 tests: a = 2, 7, and 61. For numbers in the uint64_t range it's 12 tests.
If you have a large array of integers then computing all primes up to some maximum might be faster than repeated tests. See Sieve of Eratosthenes for a good way to compute all primes fast. But it's impractical if your input numbers can be larger than 4 billion due to the memory required.
Here is some code that computes a Sieve up to UINT32_MAX+1 and then checks Miller-Rabin has the same results as the sieve: https://gist.github.com/mrvn/137fb0c8a5c78dbf92108b696ff82d92
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) return 1;
if (d == 1) return a;
uint32_t t = pow_n(a, d / 2, n);
t = ((uint64_t)t * t) % n;
if (d % 2 == 0) {
return t;
} else {
return ((uint64_t)t * a) % n;
}
};
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
//std::cout << "test(n = " << n << ", s = " << s << ", d = " << d << ", a = " << a << ")\n";
uint32_t x = pow_n(a ,d ,n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u};
static const std::array bounds{
2'047llu, 1'373'653llu, 25'326'001llu, 3'215'031'751llu,
2'152'302'898'747llu, 3'474'749'660'383llu,
341'550'071'728'321llu, 341'550'071'728'321llu /* no bounds for 19 */,
3'825'123'056'546'413'051llu,
3'825'123'056'546'413'051llu /* no bound for 29 */,
3'825'123'056'546'413'051llu /* no bound for 31 */,
(unsigned long long)UINT64_MAX /* off by a bit but it's the last bounds */,
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
template<std::size_t N>
auto composite() {
std::bitset<N / 2 + 1> is_composite;
for (uint32_t i = 3; (uint64_t)i * i < N; i += 2) {
if (is_composite[i / 2]) continue;
for (uint64_t j = i * i; j < N; j += 2 * i) is_composite[j / 2] = true;
}
return is_composite;
}
bool slow_prime(uint32_t n) {
static const auto is_composite = composite<UINT32_MAX + 1llu>();
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
return !is_composite.test(n / 2);
}
int main() {
/*
std::cout << "2047: ";
bool fast = is_prime(2047);
bool slow = slow_prime(2047);
std::cout << (fast ? "fast prime" : "");
std::cout << (slow ? "slow prime" : "");
std::cout << std::endl;
*/
//std::cout << "2: prime\n";
for (uint64_t i = 0; i <= UINT32_MAX; ++i) {
if (i % 1000000 == 1) { std::cout << "\r" << i << " "; std::cout.flush(); }
bool fast = is_prime(i);
bool slow = slow_prime(i);
if (fast != slow) std::cout << i << std::endl;
assert(fast == slow);
//std::cout << i << ": " << (is_prime(i) ? "prime" : "") << std::endl;
}
}
The sieve takes ~15s to compute and uses 256MB of memory, verifying Miller-Rabin takes ~12m45s or 765 times slower than the sieve. Which tells me that if you are testing more than 85 million 32bit numbers for primes then just compute them all with a sieve. Since the sieve is O(n^2) it only gets better if your maximum input is smaller.
I'm trying to solve this problem:
Given three integers N, L, and R, find the integer M between L and R (inclusive) that maximizes M|N (the bitwise-OR of M and N). If there are multiple such values of M, return the least of them.
For example: N=100,L=50,R=60. The result is 59. Because 100|59 reaches the maximum value and 50<=59<=60.
This is my attempt:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ll n,m,l,r,i,tmp,res,first,second,vt,dau,third=0,aka,check_high=0;
while(cin>>n>>l>>r){
tmp=0;dau=0;
for(i=31;i>=0;i--){
first = (l>>i)&1;
second = (r>>i)&1;
third = (n>>i)&1;
if(first==0&&second==0&&dau==0) continue;
dau=1;
if(first==1&&dau==1&&tmp==0) {tmp|=(1<<i);continue;}
if(first==0&&dau==1&&tmp==0) if(third==0) {tmp|=(1<<i);continue;}
if(first==0&&second==0&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==0&&second==1&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==1&&second==0&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==1&&second==1&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
}
cout<<tmp<<'\n';
}
return 0;
}
My idea is to browse each bit from left to right (it's mean form 31'st bit down to 0's bit) of L,R,N. Then, use the comparative statement to find the number M that satisfies the problem , specifically like above.
But when submit solution, I got Wrong Answer, this means, my algorithm is false, ans I'm stucking in ideal so solve this problem, can you help me this stuck ?
Without params validation
uint32_t getM(uint32_t L, uint32_t R, uint32_t N) {
auto M = L;
for (int bit = sizeof(L) * 8; bit > 0;) {
const decltype(L) value = 1 << (--bit);
if (value & N) {
if (value & M) {
decltype(L) check_value = M & (~value);
for (int i = bit; i > 0;) {
check_value |= (1 << (--i));
}
if (check_value >= L) {
M = check_value;
}
}
}
else {
if (!(value & M)) {
decltype(L) check_value = M | value;
for (int i = bit; i > 0;) {
check_value &= (~(1 << (--i)));
}
if (check_value <= R) {
M = check_value;
}
}
}
}
return M;
}
int main(int, char**)
{
std::cout << "M=" << getM(50, 60, 100) << std::endl;
std::cout << "M=" << getM(184, 270, 103) << std::endl;
return 0;
}
Output:
M=59
M=264
I'm trying to write a small program that can read and write 12 bit. The Input shouldn't have any issues but I'll include it so you understand the problem better. The input should be created as sample.lzw by the OFStream12Bits.cpp/main.cpp included below and the output should be reading the sample.lzw back from the write functions. I'm having problems with the output and getting code mismatch in the main when reading the code. I think the issues is from the operator>> and the readBit functions not sure exactly though.
Thank you very much for any help, I've been stuck on this for awhile!
The instructions for the readbit are as follows...
//basic readBit
//read12Bits(): 12Bit =
//declare Result : 12Bit = 0;
//for i = 1 to 12
//do
//declare lBit : Bit = get bit from input
//if(lBit == 1)
//then Result = (1 << (i-1)) + Result; //set bit at index i
//od
//return result
The part I don't understand is I need to return *this but there is no + operator so I can't use result to set the bit at index i. at the moment I have the code like this.
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
//int Result = a12BitValue;
//a12BitValue = ((a12BitValue & 0x0fff) << 1);
a12BitValue = a12BitValue & 0x0fff;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
Also The instructions for the readBit are as follows...
//implements mapping process. returns 0 or 1 depending on value of fBuffer[fByteIndex] & (1 << (fBitIndex - 1))
//see how it works with experiments
//at start check if (fByteCount == 0){reload();} then use reload() called as buffer does not contain any data before calling reload
//next fetch the bit store and then advance fByteIndex and fBitIndex
//if fBitIndex(highest to lowest) reaches 0 you need to switch to the next byte in the buffer. and also decrment fByteCount
//then finally return result
And the code is
int IFStream12Bits::readBit()
{
if (fByteCount == 0){ reload(); }
//int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int result = 0;
cout << "bit: " << bit << endl;
//added this just cause
if (bit == 0)
{
result = 0;
}
else
{
result = 1;
}
//additional logic required?
fByteIndex++;
fBitIndex--;
//switch to next byte in the buffer
if (fBitIndex == 0)
{
fByteCount--;
fBitIndex = 8;
fByteIndex = 0;
}
return result;
}
Here are the full .cpp files if you need to understand what is happening...
IFStream12Bits.cpp
#include "IFStream12Bits.h"
#include <iostream>
using namespace std;
//default constructor
IFStream12Bits::IFStream12Bits()
{
init();
}
//takes aFIleName
IFStream12Bits::IFStream12Bits(const char* aFileName)
{
init();
open(aFileName);
}
//deconstructor
IFStream12Bits::~IFStream12Bits()
{
close();
}
//initialize the integer member variables with sensible values
//:fBuffer(), fByteCount(0), fByteIndex(0), fBitIndex(8)
//fBitIndex(highToLow)
void IFStream12Bits::init()
{
for (int i = 0; i < 32; i++)
{
fBuffer[i] = 0;
}
fByteCount = 0;
fByteIndex = 0;
fBitIndex = 8;
}
//fills input buffer fBuffer with the next 32 bytes and sets fByteCount to number of bytes read
void IFStream12Bits::reload()
{
//fills fBuffer with 32 bytes
fIStream.read((char*)fBuffer, 32);
//fIStream.read((char*)fBuffer, fByteIndex + (fBitIndex % 8 ? 1 : 0));
//sets fByteCount to number of bytes read
fByteCount = fIStream.gcount();
}
//implements mapping process. returns 0 or 1 depending on value of fBuffer[fByteIndex] & (1 << (fBitIndex - 1))
//see how it works with experiments
//at start check if (fByteCount == 0){reload();} then use reload() called as buffer does not contain any data before calling reload
//next fetch the bit store and then advance fByteIndex and fBitIndex
//if fBitIndex(highest to lowest) reaches 0 you need to switch to the next byte in the buffer. and also decrment fByteCount
//then finally return result
int IFStream12Bits::readBit()
{
if (fByteCount == 0){ reload(); }
//int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int result = 0;
cout << "bit: " << bit << endl;
if (bit == 0)
{
result = 0;
}
else
{
result = 1;
}
//additional logic required?
fByteIndex++;
fBitIndex--;
//switch to next byte in the buffer
if (fBitIndex == 0)
{
fByteCount--;
fBitIndex = 8;
fByteIndex = 0;
}
return result;
}
void IFStream12Bits::open(const char* aFileName)
{
fIStream.open(aFileName, std::fstream::binary);
}
void IFStream12Bits::close()
{
fIStream.close();
}
bool IFStream12Bits::fail()
{
return fIStream.fail();
}
//true if no bytes left in input stream (fByteCount == 0)(should be zero if never read anythign from fIStream)
bool IFStream12Bits::eof()
{
return fByteCount == 0;
}
//read 12Bit codes from the bit input stream implements the read12Bits algorithm as shown in the tutorial
//basic readBit
//read12Bits(): 12Bit =
//declare Result : 12Bit = 0;
//for i = 1 to 12
//do
//declare lBit : Bit = get bit from input
//if(lBit == 1)
//then Result = (1 << (i-1)) + Result; //set bit at index i
//od
//return result
// multiply values by 2 to shift left???????????
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
//int Result = a12BitValue;
//a12BitValue = ((a12BitValue & 0x0fff) << 1);
a12BitValue = a12BitValue & 0x0fff;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
OFStream12Bits.cpp
#include "OFStream12Bits.h"
OFStream12Bits::OFStream12Bits()
{
init();
}
OFStream12Bits::OFStream12Bits(const char* aFileName)
{
init();
open(aFileName);
}
OFStream12Bits::~OFStream12Bits()
{
close();
}
void OFStream12Bits::init()
{
for (int i = 0; i < 32; i++)
{
fBuffer[i] = 0;
}
fByteIndex = 0;
fBitIndex = 8;
}
void OFStream12Bits::writeBit0()
{
fBitIndex--;
finishWriteBit();
}
void OFStream12Bits::writeBit1()
{
fBuffer[fByteIndex] += 1 << (fBitIndex - 1);
fBitIndex--;
finishWriteBit();
}
void OFStream12Bits::finishWriteBit()
{
if (fBitIndex == 0)
{
if (fByteIndex == 31)
{
fByteIndex++;
//write full buffer to stream
flush();
}
else
{
fByteIndex++;
fBitIndex = 8;
}
}
}
void OFStream12Bits::open(const char* aFileName)
{
fOStream.open(aFileName, std::ofstream::binary);
}
bool OFStream12Bits::fail()
{
return fOStream.fail();
}
void OFStream12Bits::close()
{
flush();
fOStream.close();
}
void OFStream12Bits::flush()
{
// do we need to add last byte?
fOStream.write((char*)fBuffer, fByteIndex + (fBitIndex % 8 ? 1 : 0));
init();
}
OFStream12Bits& OFStream12Bits::operator<<(int a12BitValue)
{
a12BitValue = a12BitValue & 0x0fff; // mask 12 lower bits
for (int i = 0; i < 12; i++) //write 12 bits
{
if (a12BitValue & 0x01) // the current lowest bit is set
{
writeBit1();
}
else
{
writeBit0();
}
a12BitValue >>= 1; // code = code / 2 --shifting value accross
}
return *this;
}
main.cpp
#include "OFStream12Bits.h"
#include "IFStream12Bits.h"
#include <iostream>
using namespace std;
void write4096()
{
cout << "Write 4096 codes" << endl;
OFStream12Bits lWriter("sample.lzw");
if (lWriter.fail())
{
cerr << "Error: unable to open output file" << endl;
exit(1);
}
for (int i = 4096; i >= 0; i--)
{
lWriter << i;
}
}
void read4096()
{
cout << "Read 4096 codes" << endl;
IFStream12Bits lInput("sample.lzw");
if (lInput.fail())
{
cerr << "Error: unable to open input file!" << endl;
exit(2);
}
for (int i = 4095; i >= 0; i--)
{
int l12BitValue;
lInput >> l12BitValue;
if (l12BitValue != i)
{
cerr << "Error: Code mismatch: " << l12BitValue << " != " << i << endl;
exit(3);
}
}
if (!lInput.eof())
{
cerr << "Error: Input stream not exhausted" << endl;
}
}
int main()
{
write4096();
read4096();
cout << "SUCCESS" << endl;
return 0;
}
Your input code is starting with the previous value. You should start with 0, because you're not clearing bits that aren't set.
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
a12BitValue = 0;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
Also, + will work here, but it's clearer to use bitwise operations when dealing with bits. Additionally, I think your shift is off. I would write the set bit line like this:
a12BitValue |= 1 << i;
If you think about it, when i is 0, you want to set the first bit (which is 1 or 1 << 0.) When i is 1, you want the next bit, and so on. So you should not need to subtract one.
I'm not sure that's the only problem, but you might try testing each class independently with unit tests. For example, start with a raw byte buffer, like {0x89, 0xAB, 0xCD, 0xEF, 0x01}, and then read three sets of 12 bits off. Verify they are correct. Then create an empty buffer, and write specific bits to it, and check that the bytes are correct.
By testing the algorithms independently, and with very strict input/output, you'll find it much easier to determine the flaw.
I'm trying to implement a function that writes double to binary file in little endian byte order.
So far I have class BinaryWriter implementation:
void BinaryWriter::open_file_stream( const String& path )
{
// open output stream
m_fstream.open( path.c_str(), std::ios_base::out | std::ios_base::binary);
m_fstream.imbue(std::locale::classic());
}
void BinaryWriter::write( int v )
{
char data[4];
data[0] = static_cast<char>(v & 0xFF);
data[1] = static_cast<char>((v >> 8) & 0xFF);
data[2] = static_cast<char>((v >> 16) & 0xFF);
data[3] = static_cast<char>((v >> 24) & 0xFF);
m_fstream.write(data, 4);
}
void BinaryWriter::write( double v )
{
// TBD
}
void BinaryWriter::write( int v ) was implemented using Sven answer to What is the correct way to output hex data to a file? post.
Not sure how to implement void BinaryWriter::write( double v ).
I tried naively follow void BinaryWriter::write( int v ) implementation but it didn't work. I guess I don't fully understand the implementation.
Thank you guys
You didn't write this, but I'm assuming the machine you're running on is BIG endian, otherwise writing a double is the same as writing an int, only it's 8 bytes.
const int __one__ = 1;
const bool isCpuLittleEndian = 1 == *(char*)(&__one__); // CPU endianness
const bool isFileLittleEndian = false; // output endianness - you choose :)
void BinaryWriter::write( double v )
{
if (isCpuLittleEndian ^ isFileLittleEndian) {
char data[8], *pDouble = (char*)(double*)(&v);
for (int i = 0; i < 8; ++i) {
data[i] = pDouble[7-i];
}
m_fstream.write(data, 8);
}
else
m_fstream.write((char*)(&v), 8);
}
But don't forget generally int is 4 octects and double is 8 octets.
Other problem is static_cast. See this example :
double d = 6.1;
char c = static_cast(d); //c == 6
Solution reinterpret value with pointer :
double d = 6.1;
char* c = reinterpret_cast<char*>(&d);
After, you can use write( Int_64 *v ), which is a extension from write( Int_t v ).
You can use this method with :
double d = 45612.9874
binary_writer.write64(reinterpret_cast<int_64*>(&d));
Don't forget size_of(double) depend of system.
A little program converting doubles to an IEEE little endian representation.
Besides the test in to_little_endian, it should work on any machine.
include <cmath>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <limits>
#include <sstream>
#include <random>
bool to_little_endian(double value) {
enum { zero_exponent = 0x3ff };
uint8_t sgn = 0; // 1 bit
uint16_t exponent = 0; // 11 bits
uint64_t fraction = 0; // 52 bits
double d = value;
if(std::signbit(d)) {
sgn = 1;
d = -d;
}
if(std::isinf(d)) {
exponent = 0x7ff;
}
else if(std::isnan(d)) {
exponent = 0x7ff;
fraction = 0x8000000000000;
}
else if(d) {
int e;
double f = frexp(d, &e);
// A leading one is implicit.
// Hence one has has a zero fraction and the zero_exponent:
exponent = uint16_t(e + zero_exponent - 1);
unsigned bits = 0;
while(f) {
f *= 2;
fraction <<= 1;
if (1 <= f) {
fraction |= 1;
f -= 1;
}
++bits;
}
fraction = (fraction << (53 - bits)) & ((uint64_t(1) << 52) - 1);
}
// Little endian representation.
uint8_t data[sizeof(double)];
for(unsigned i = 0; i < 6; ++i) {
data[i] = fraction & 0xFF;
fraction >>= 8;
}
data[6] = (exponent << 4) | fraction;
data[7] = (sgn << 7) | (exponent >> 4);
// This test works on a little endian machine, only.
double result = *(double*) &data;
if(result == value || (std::isnan(result) && std::isnan(value))) return true;
else {
struct DoubleLittleEndian {
uint64_t fraction : 52;
uint64_t exp : 11;
uint64_t sgn : 1;
};
DoubleLittleEndian little_endian;
std::memcpy(&little_endian, &data, sizeof(double));
std::cout << std::hex
<< " Result: " << result << '\n'
<< "Fraction: " << little_endian.fraction << '\n'
<< " Exp: " << little_endian.exp << '\n'
<< " Sgn: " << little_endian.sgn << '\n'
<< std::endl;
std::memcpy(&little_endian, &value, sizeof(value));
std::cout << std::hex
<< " Value: " << value << '\n'
<< "Fraction: " << little_endian.fraction << '\n'
<< " Exp: " << little_endian.exp << '\n'
<< " Sgn: " << little_endian.sgn
<< std::endl;
return false;
}
}
int main()
{
to_little_endian(+1.0);
to_little_endian(+0.0);
to_little_endian(-0.0);
to_little_endian(+std::numeric_limits<double>::infinity());
to_little_endian(-std::numeric_limits<double>::infinity());
to_little_endian(std::numeric_limits<double>::quiet_NaN());
std::uniform_real_distribution<double> distribute(-100, +100);
std::default_random_engine random;
for (unsigned loop = 0; loop < 10000; ++loop) {
double value = distribute(random);
to_little_endian(value);
}
return 0;
}
I'm coding an exercise from a book. This program should set a "bitmapped graphics device" bits, and then check for any of them if they are 1 or 0. The setting function was already written so I only wrote the test_bit function, but it doesn't work.
In the main() I set the first byte's first bit to 1, so the byte is 10000000, then I want to test it: 10000000 & 10000000 == 10000000, so not null, but I still get false when I want to print it out. What's wrong?
#include <iostream>
const int X_SIZE = 32;
const int Y_SIZE = 24;
char graphics[X_SIZE / 8][Y_SIZE];
inline void set_bit(const int x, const int y)
{
graphics[(x)/8][y] |= (0x80 >> ((x)%8));
}
inline bool test_bit(const int x, const int y)
{
return (graphics[x/8][y] & (0x80 >> ((x)%8)) != 0);
}
void print_graphics(void) //this function simulate the bitmapped graphics device
{
int x;
int y;
int bit;
for(y=0; y < Y_SIZE; y++)
{
for(x = 0; x < X_SIZE / 8; x++)
{
for(bit = 0x80;bit > 0; bit = (bit >> 1))
{
if((graphics[x][y] & bit) != 0)
std::cout << 'X';
else
std::cout << '.';
}
}
std::cout << '\n';
}
}
main()
{
int loc;
for (loc = 0; loc < X_SIZE; loc++)
{
set_bit(loc,loc);
}
print_graphics();
std::cout << "Bit(0,0): " << test_bit(0,0) << std::endl;
return 0;
}
In MSVC++, I get a compiler warning (C4554 'operator' : check operator precedence for possible error; use parentheses to clarify precedence)
Add parentheses, and it works, like this:
inline bool test_bit(const int x, const int y)
{
return ( ( graphics[x/8][y] & (0x80 >> ((x)%8)) ) != 0);
// ^ ^ Added parentheses
}
Explanation:
The problem is with order. The original line will first evalute (0x80 >> ((x)%8) != 0, which is true, or 1 as integer. and 0x80 & 0x01 then yields 0, or false resp.
I think you want 0x80>> not 1>> in test_bit. Shifting one right tends to produce zero.
Also you need to write (a & b) != 0. The precedence of == and != is higher than that of &, so a & b != 0 is parsed as if it was written a & (b != 0). (An old C / C++ gotcha.)