finding the first set bit in a binary number [duplicate] - c++

This question already has answers here:
Efficient bitwise operations for counting bits or find the right|left most ones
(6 answers)
Position of least significant bit that is set
(23 answers)
Closed 9 years ago.
I need to find the first set bit in a binary number from right to left; I came up with this solution:
int cnt=0;
while (number& 1 ==0)
{
cnt++;
number>>=1;
}
Is there a better way of doing it? Some clever bit manipulation technique?

processor may have instruction to find that directly:
Windows/MSVC:
_BitScanForward()
_BitScanReverse()
GCC:
__builtin_ffs()
__builtin_ctz()
__builtin_clz()
These typically map directly to native hardware instructions. So it doesn't get much faster than these.
But since there's no C/C++ functionality for them, they're only accessible via compiler intrinsics.
You can do it manually that way:
n & (n - 1) is a technique to remove the rightmost set bit.
So, n - (n & n - 1) will return a number with only the rightmost set bit.
then a 'log2' of the result give the solution: this link may help
You may alternatively use a switch case with all 1 << k will give you the solution
switch (n - (n & n - 1)) {
case 0: ...
case 1 << 0: return 0;
case 1 << 1: return 1;
...
}

If you want it to be fast, bitscan instruction (bsf, bsr) or bit-twiddling hack is the target to go.
EDIT:
The idea of using switch-case table to improve performance is nothing but immature.

Bit Twiddling Hacks offers an excellent collection of, er, bit twiddling hacks, with performance/optimisation discussion attached. For your problem (from that site), you can use multiply-and-lookup strategy:
unsigned int c = number; // your input number
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((c & -c) * 0x077CB531U)) >> 27];

Your code
int cnt=0;
while (number& 1 ==0)
{
cnt++;
number>>=1;
}
has a bug. For example if number is equal to 0 then the loop will be infinite.
I would rewrite it the following way
int cnt = 0;
if ( number ) while ( !( number & ( 1 << cnt++ ) ) );
In this case if number is not equal to 0 then the position (cnt) of the set bit will be count starting from 1. Otherwise the position will be equal to 0.

I'm not sure the accepted answer is right. I just tested the naive loop versus the (num & -num) solution. They are both the same speed. The naive loop is much less code. I built with:
gcc 4.7.2 from MinGW, on Win 7
gcc test.c -o test.exe -std=c99 -Wall -O2
Here's my code (it probably has some corner case bugs, but I suspect the timings are roughly valid).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_NUMS 65536
int find_first_bits(unsigned nums[NUM_NUMS])
{
int total = 0; // Prevent compiler from optimizing out the code
for (int j = 0; j < 10000; j++) {
for (int i = 0; i < NUM_NUMS; i++) {
switch (nums[i] & -nums[i]) {
case (1<<0): total += 1; break;
case (1<<1): total += 2; break;
case (1<<2): total += 3; break;
case (1<<3): total += 4; break;
case (1<<4): total += 5; break;
case (1<<5): total += 6; break;
case (1<<6): total += 7; break;
case (1<<7): total += 8; break;
case (1<<8): total += 9; break;
case (1<<9): total += 10; break;
case (1<<10): total += 11; break;
case (1<<11): total += 12; break;
case (1<<12): total += 13; break;
case (1<<13): total += 14; break;
case (1<<14): total += 15; break;
case (1<<15): total += 16; break;
case (1<<16): total += 17; break;
case (1<<17): total += 18; break;
case (1<<18): total += 19; break;
case (1<<19): total += 20; break;
case (1<<20): total += 21; break;
case (1<<21): total += 22; break;
case (1<<22): total += 23; break;
case (1<<23): total += 24; break;
case (1<<24): total += 25; break;
case (1<<25): total += 26; break;
case (1<<26): total += 27; break;
case (1<<27): total += 28; break;
case (1<<28): total += 29; break;
case (1<<29): total += 30; break;
case (1<<30): total += 31; break;
case (1<<31): total += 32; break;
}
}
}
return total;
}
int find_first_bits2(unsigned nums[NUM_NUMS])
{
int total = 0; // Prevent compiler from optimizing out the code
for (int j = 0; j < 10000; j++) {
for (int i = 0; i < NUM_NUMS; i++) {
unsigned mask = 1;
for (int cnt = 1; cnt <= 32; cnt++, mask <<= 1) {
if (nums[i] & mask) {
total += cnt;
break;
}
}
}
}
return total;
}
int main() {
// Create some random data to test
unsigned nums[NUM_NUMS];
for (int i = 0; i < NUM_NUMS; i++) {
nums[i] = rand() + (rand() << 15);
}
clock_t start_time, end_time;
int result;
start_time = clock();
result = find_first_bits(nums);
end_time = clock();
printf("Time = %.5f, result = %d\n", (end_time - start_time) / (double)(CLOCKS_PER_SEC), result);
start_time = clock();
result = find_first_bits2(nums);
end_time = clock();
printf("Time = %.5f, result = %d\n", (end_time - start_time) / (double)(CLOCKS_PER_SEC), result);
}

Related

I need to find the integer value for the given roman number. I can't get the solution

I used my logic, I am confident my logic was correct,but for some reasons my code doesn't work. I need help to point out what mistake I made, also sorry for declaring my variables as
random alphabets without any semantic meaning.
#include<iostream>
using namespace std;
int main()
{
char s[15];
cin >> s;
char a[7] = {'I','V','X','L', 'C', 'D', 'M'};
int b[7] = {1,5,10,50,100,500,1000};
int count = 0,i=0,j,k;
while(s[i]!='\0')
{
for(j=0;j<7;j++)
{
int l=0;
if(s[i]==a[j])
{
k = j;
if(s[i+1] == a[j])
{
l = j;
}
}
if(k<l)
{
count = count + (b[l]-b[k]);
i+=2;
}
else
{
count = count + b[k];
i++;
}
}
}
cout << count;
}
The solution:
int romanCharToInt(char c) {
switch(c) {
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
}
return 0;
}
int romanToInt(string s) {
int result = 0;
int stored_sum = 0;
int last_val = -1;
for (char elem : s) {
int val = romanCharToInt(elem);
if (last_val == -1) {
stored_sum += val;
} else if (last_val > val) {
result += stored_sum;
stored_sum = val;
} else if (last_val == val) {
stored_sum += val;
} else {
stored_sum = val - stored_sum;
}
last_val = val;
}
result += stored_sum;
stored_sum = 0;
return result;
}
This looks like a homework assignment, and while I think you should go back to the drawing board in order to figure this out, maybe a hint would suffice.
When we analyze a roman integer, it has it's most significant 'digits'(letters) closer to the start of it. The only exception is when the 'digit' directly to the right of it is of higher order.
You may find it easier to solve the problem from the least significant digits forward.
Given this scenario, the procedure I'd follow is this:
Number : MCMXCIV
Current Roman Digit | Current Answer int
V | 5 (no matter what the first character is, it will always be the base)
I | 5 - 1 (I is smaller than V, therefore we substract it)
C | 5 - 1 + 100
X | 5 - 1 + 100 - 10 (X is smaller than C, we substract)
M | 5 - 1 + 100 - 10 + 1000
C | 5 - 1 + 100 - 10 + 1000 - 100
M | 5 - 1 + 100 - 10 + 1000 - 100 + 1000 = 1994

What is the correct way to transform the formula for the determination of the day of the week into C++?

I have an assignment where I need to figure out which day of the week a date was/is. The formula on Wikipedia goes as following
where
d = day (1-31)
m = month (starting with March = 1 up to February=12)
y = last 2 digits of a year
c = first 2 digits of a year
(y and c must be reduced by 1 if the month is January or February)
My function goes as follows:
int wochentagWiki(int inttag, int intmonat, int intjahr) {
int d = inttag;
int m = 0;
switch (intmonat) {
case 1:
m = 11;
break;
case 2:
m = 12;
break;
case 3:
m = 1;
break;
case 4:
m = 2;
break;
case 5:
m = 3;
break;
case 6:
m = 4;
break;
case 7:
m = 5;
break;
case 8:
m = 6;
break;
case 9:
m = 7;
break;
case 10:
m = 8;
break;
case 11:
m = 9;
break;
case 12:
m = 10;
break;
}
int y = intjahr % 100;
if (intmonat == 1 || intmonat == 2) {
y--;
}
int c = intjahr / 100;
if (intmonat == 1 || intmonat == 2) {
c--;
}
int w = (d + (2.6 * m - 0.2) + y + (y / 4) + (c / 4) - (__int64)2 * c) % 7;
return w;
}
My problem is that w always returns a wrong value, and I think it's because I translated the formula the wrong way. What would be the correct way to write it down?
It looks to me like you've made a mistake in copying down the formula:
(y and c must be reduced by 1 if the month is January or February)
But Wikipedia says:
Y is the year minus 1 for January or February, and the year for any other month
y is the last 2 digits of Y
c is the first 2 digits of Y

c++ Increasing for loop increment logarithmically

I want to loop though integers like this:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, ..., 100, 200, ..., 1000, 2000, ...
I have code to do this (shown below) however it is cumbersome and not programmed generally to deal with different stopping limits:
int MAX = 10000;
for (int i = 1; i <= MAX; i++) {
cout << i << endl;
if (i >= 10 && i < 100) {
i += 9;
}
else if (i >= 100 && i < 1000) {
i+= 99;
}
else if (i >= 1000 && i < 10000) {
i += 999;
}
}
As you can see, this is very situation specified as mentioned previously - so I'd like to know of a way to code this in a more general way, as for my requirements MAX will be of the order of 10^9 so using code like above is far too impractical.
Try this code. It is more general:
int MAX = 1000000;
for (int i = 1, increment = 1, counter = 1; i <= MAX; i += increment) {
cout << i << endl;
if (counter == 10) {
increment *= 10;
counter = 1;
}
++counter;
}

Am I using this switch case incorrectly?

So the idea of this program is to get the users input in the form of a Roman Numeral up to 4999. I decided to use a switch case to loop through an string of input. The problem is when I put in a value like 99 which would be XCIX it returns -101. Any help is grateful.
int number = 0, M = 1000, D = 500, C = 100, L = 50, X = 10, V = 5, I = 1;
for (int i = 0; i < roman.length(); i++)
{
switch (roman[i])
{
case 'M': number += 1000; break;
case 'D': if (roman[i + 1] != 'D' && i + 1 < roman.size())
number -= 500;
else
number += 500;
break;
case 'C': if (roman[i + 1] != 'C' && i + 1 < roman.size())
number -= 100;
else
number += 100;
break;
case 'L': if (roman[i + 1] != 'L' && i + 1 < roman.size())
number -= 50;
else
number += 50;
break;
case 'X': if (roman[i + 1] != 'X' && i + 1 < roman.size())
number -= 10;
else
number += 10;
break;
case 'V': if (roman[i + 1] != 'V' && i + 1 < roman.size())
number -= 5;
else
number += 5;
break;
case 'I':
if (roman[i + 1] != 'I' && i + 1 < roman.size())
number -= 1;
else
number += 1;
break;
}
}
return number;
Roman numerals count negative only when they appear before a digit with higher value. Being different is not enough.

Poker code cleanup modification from book...not quite right

Working through more book examples- this one is a partial poker program-
This segment deals with straight hand....
First what was given- only relevant parts....will provide entire code if needed...
int suits[5]; //index 1..4- value start at 1
int values[14]; //index 1..13- value same as rank, A = 1, K = 13
cin.get(rankCh);
switch (toUpper(rankCh)) {
case 'A': values = 1; break;
case '2': values = 2; break;
case '3': values = 3; break;
case '4': values = 4; break;
case '5': values = 5; break;
case '6': values = 6; break;
case '7': values = 7; break;
case '8': values = 8; break;
case '9': values = 9; break;
case 'T': values = 10; break;
case 'J': values = 11; break;
case 'Q': values = 12; break;
case 'K': values = 13; break;
default:
badCard = true;
}
Other functions:
bool isFlush(int suits[]) {
for(i = 1; i <= 4; i++)
if (suits[i] == 5) //5 here is Number of Cards
return true;
return false;
}
Yeah, I know about the array declarations but that is how it is defined- nice justification for it in the text...starting to number at 1
I want my straight hand to handle both Ace high and low- right now as define above aces are low...
Two versions: 1st appears not sure correct with low aces...
CODE
bool isStraight(int values[]) //Version one only straight- low aces only
{
int count = 0;
for (i = 1; i <= 13; i++) {
if (values[i] != 1) {
count++;
} else
count = 0;
if (count == 5) //5 is NUMCARDS
return true;
}
return false;
}
Now this is the where I need some recommendation: to have a function to handle both ace high and low:
bool isStraight(int values[]) //Version handles both high and low
{
int count = 0;
for (i = 1; i <= 13; i++) {
if (values[i] != 1) {
count++;
// if(i == 1 && values[1] != 0) //Check for high and low
// count++;
} else
count = 0;
if (count == 5) //5 is NUMCARDS
return true;
}
return false;
}
Would what I have in comments work to handle both ace high and low...
Since i = 1 is represented as ace and not sure what values[1] is correct should it be values[13] or what...maybe something like
if (i == 1)
values[13] //not sure...
Recommendations-
do not want wholesale changes- just to have minor changes with what I have...I do not want to sort or solve by brute force i.e like values[1] == 1 && values [2] ==1 you get the point- the text does that already but I am trying to rewrite it this way...
Thanks...Hope I am getting across my modification I would like...
EDIT: I figured I'd would first answer your question directly. Lets first clear up how the original algorithm worked. Basically it loops from 1 to 13, and each time it sees a card in that slot, it adds to count. If anything ever breaks the sequence, it resets the counter. Finally, if the counter reaches 5, you have a straight.
I can't say off hand if your solution would work, I say give it a go. However, a simple quick patch to the original would probably go something like this:
//Version handles both high and low
bool isStraight(int values[]) {
int count = 0;
for (i = 1; i <= 13; i++) {
if (values[i] != 1) {
count++;
} else
count = 0;
if (count == 5) //5 is NUMCARDS
return true;
}
// handle ace high.
if(count == 4 && values[1] != 0) {
return true;
}
return false;
}
Basically what that does is say "if we already have 4 in a row, and we've just looked at the very last card (the loop is over), then check an ace is there, if so, we do have a straight and it is ace high".
ORIGINAL ANSWER:
I think the easiest way to handle ace high and low is to have the "get rank" function have two modes, one which returns ace high, the other which returns ace low. Then just calculate the hand value for each case and take the better one.
Also, your get rank could be way simpler :-P.
int get_rank(char card) {
static const char *cards = "A23456789TJQK";
char *p = strchr(cards, toupper(card));
if(p) {
return (p - cards) + 1;
} else {
return -1;
}
}
so if you want to have a get_rank which has an ace_high or an ace_low, you could do this:
int get_rank(char card, bool ace_high) {
static const char *cards_high = "23456789TJQKA";
static const char *cards_low = "A23456789TJQK";
const char *cards = ace_high ? cards_high : cards_low;
char *p = strchr(cards, toupper(card));
if(p) {
return (p - cards) + 1;
} else {
return -1;
}
}
EDIT:
for fun, i've made a quick and dirty program which detects straights (handling both high and low ace). It is fairly simple, but could be shorter (also note that there is no attempt at buffer safety with these arrays, something of production quality should use something safer such as std::vector:
#include <algorithm>
#include <iostream>
#include <cstring>
int get_rank(char card, bool ace_high) {
static const char *cards_high = "23456789TJQKA";
static const char *cards_low = "A23456789TJQK";
const char *cards = ace_high ? cards_high : cards_low;
char *p = strchr(cards, toupper(card));
if(p) {
return (p - cards) + 1;
} else {
return -1;
}
}
bool is_rank_less_low(int card1, int card2) {
return get_rank(card1, false) < get_rank(card2, false);
}
bool is_rank_less_high(int card1, int card2) {
return get_rank(card1, true) < get_rank(card2, true);
}
bool is_straight(int hand[], bool ace_high) {
std::sort(hand, hand + 5, ace_high ? is_rank_less_high : is_rank_less_low);
int rank = get_rank(hand[0], ace_high);
for(int i = 1; i < 5; ++i) {
int new_rank = get_rank(hand[i], ace_high);
if(new_rank != rank + 1) {
return false;
}
rank = new_rank;
}
return true;
}
bool is_straight(int hand[]) {
return is_straight(hand, false) || is_straight(hand, true);
}
int main() {
int hand1[5] = { 'T', 'J', 'Q', 'K', 'A' };
int hand2[5] = { 'A', '2', '3', '4', '5' };
std::cout << is_straight(hand1) << std::endl;
std::cout << is_straight(hand2) << std::endl;
}
The case where an ace-high straight exists can be found by changing the final test:
if (count == 5 || count == 4 && values[1] == 1) // 2nd case handles ace-high straight
return true;
It's a special case, so it must be handled separately.