Goldbach conjecture exercise (c) - c

My professor asked me to do a program to test the Goldbach conjecture. I am wondering if I should consider 1 as a prime. This is my code that prints the first combination of prime numbers:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n, i, j, k, l;
char prime, prime1;
do //check if n is even and greater than 2
{
printf("Give me an even natural number greater than 2:\n\n>");
scanf("%d", &n);
}
while (n % 2 != 0 && n >= 2);
for (i = 1; i < n ; i++)
{
prime = 1;
for (k = 2; k < i; k++)
if (i % k == 0)
prime = 0;
if (prime)
{
for (j = 1; j < n; j++)
{
prime1 = 1;
for (l = 2; l < j; l++)
if (j % l == 0)
prime1 = 0;
if (prime1)
if (i + j == n)
{
printf("\n\n%d and %d are the first two prime numbers that add up to %d.\n", i, j, n);
return 0;
}
}
}
}
}
I checked the internet and almost everyone says that 1 is not a prime. What should i do? Keep the program as it is or change it so that it won't consider 1 as a prime? And how do I do that? :P

you can consider 1 a prime number, as Goldbach did, or not as is the more common usage, it makes almost no difference regarding the conjecture.
Considering 1 as a prime number has this effect:
there is a solution for 2: 1 + 1.
the first pair for 4 is 1 + 3 instead of 2 + 2
the first solution for higher even numbers may involve 1 if the value is a prime number plus one, but no known even number greater than 2 can only be expressed as p + 1.
Note that there are problems in your code:
you do not check the return value of scanf(), so inputing a string that is not a number will cause undefined behavior (the first time as n is uninitialized) or an infinite loop as n is no longer modified.
the test while (n % 2 != 0 && n >= 2); is incorrect: it should be:
while (n <= 2 || n % 2 != 0);
the first loop could iterate half as long with a test i <= n / 2
the second loop could iterate much less with a test k * k <= i
you could exit the second loop when you detect that i is not prime
there is no need for a third loop, you just need to test if n - i is prime
the same improvements are possible for the second primary test, better move this to a separate function.
you should have a message and return statement for the remote possibility that you find a counter-example to the Goldbach conjecture ;-)
Here is an improved version:
#include <stdio.h>
#define PRIME_MASK ((1ULL << 2) | (1ULL << 3) | (1ULL << 5) | (1ULL << 7) |\
(1ULL << 11) | (1ULL << 13) | (1ULL << 17) | (1ULL << 19) | \
(1ULL << 23) | (1ULL << 29) | (1ULL << 31) | (1ULL << 37) | \
(1ULL << 41) | (1ULL << 43) | (1ULL << 47) | (1ULL << 53) | \
(1ULL << 59) | (1ULL << 61))
int isprime(unsigned long long n) {
if (n <= 63)
return (PRIME_MASK >> n) & 1;
if (n % 2 == 0)
return 0;
for (unsigned long long k = 3; k * k <= n; k += 2) {
if (n % k == 0)
return 0;
}
return 1;
}
int main(void) {
unsigned long long n, i;
int r;
for (;;) {
printf("Give me an even natural number greater than 2:\n>");
r = scanf("%llu", &n);
if (r == 1) {
if (n % 2 == 0 && n > 2)
break;
} else
if (r == EOF) { /* premature end of file */
return 1;
} else {
scanf("%*[^\n]%*c"); /* flush pending line */
}
}
#ifdef ONE_IS_PRIME
i = 1; /* start this loop at 1 if you want to assume 1 is prime */
#else
i = (n == 4) ? 2 : 3;
#endif
for (; i <= n / 2; i += 2) {
if (isprime(i) && isprime(n - i)) {
printf("%llu = %llu + %llu\n", n, i, n - i);
return 0;
}
}
printf("Goldbach was wrong!\n"
" %llu cannot be written as the sum of two primes\n", n);
return 0;
}

YOU CAN Consider 1 to be a prime as Goldbach too considered it to be prime in his letter to Leonhard Euler.But that was the time when 1 was considered to be prime.Later it was abandoned and hence this one is Goldbach's third revised conjecture.Also,since today we consider 1 to be neither prime nor composite,even if you don't consider 1 to be a prime number,the conjecture still holds true,is well-verified upto 4*10^18 (re-verified upto 4*10^17).
As far as you deal with the Professor,you should better ask him what does he want.

Related

random 4 digit number with non repeating digits in C

I'm trying to make a get_random_4digit function that generates a 4 digit number that has non-repeating digits ranging from 1-9 while only using ints, if, while and functions, so no arrays etc.
This is the code I have but it is not really working as intended, could anyone point me in the right direction?
int get_random_4digit() {
int d1 = rand() % 9 + 1;
int d2 = rand() % 9 + 1;
while (true) {
if (d1 != d2) {
int d3 = rand() % 9 + 1;
if (d3 != d1 || d3 != d2) {
int d4 = rand() % 9 + 1;
if (d4 != d1 || d4 != d2 || d4 != d3) {
random_4digit = (d1 * 1000) + (d2 * 100) + (d3 * 10) + d4;
break;
}
}
}
}
printf("Random 4digit = %d\n", random_4digit);
}
A KISS-approach could be this:
int getRandom4Digits() {
uint16_t acc = 0;
uint16_t used = 0;
for (int i = 0; i < 4; i++) {
int idx;
do {
idx = rand() % 9; // Not equidistributed but never mind...
} while (used & (1 << idx));
acc = acc * 10 + (idx + 1);
used |= (1 << idx);
}
return acc;
}
This looks terribly dumb at first. A quick analysis gives that this really isn't so bad, giving a number of calls to rand() to be about 4.9.
The expected number of inner loop steps [and corresponding calls to rand(), if we assume rand() % 9 to be i.i.d.] will be:
9/9 + 9/8 + 9/7 + 9/6 ~ 4.9107.
There are 9 possibilities for the first digit, 8 possibilities for the second digit, 7 possibilities for the third digit and 6 possibilities for the last digit. This works out to "9*8*7*6 = 3024 permutations".
Start by getting a random number from 0 to 3023. Let's call that P. To do this without causing a biased distribution use something like do { P = rand() & 0xFFF; } while(P >= 3024);.
Note: If you don't care about uniform distribution you could just do P = rand() % 3024;. In this case lower values of P will be more likely because RAND_MAX doesn't divide by 3024 nicely.
The first digit has 9 possibilities, so do d1 = P % 9 + 1; P = P / 9;.
The second digit has 8 possibilities, so do d2 = P % 8 + 1; P = P / 8;.
The third digit has 7 possibilities, so do d3 = P % 7 + 1; P = P / 7;.
For the last digit you can just do d4 = P + 1; because we know P can't be too high.
Next; convert "possibility" into a digit. For d1 you do nothing. For d2 you need to increase it if it's greater than or equal to d1, like if(d2 >= d1) d2++;. Do the same for d3 and d4 (comparing against all previous digits).
The final code will be something like:
int get_random_4digit() {
int P, d1, d2, d3, d4;
do {
P = rand() & 0xFFF;
} while(P >= 3024);
d1 = P % 9 + 1; P = P / 9;
d2 = P % 8 + 1; P = P / 8;
d3 = P % 7 + 1; P = P / 7;
d4 = P + 1;
if(d2 >= d1) d2++;
if(d3 >= d1) d3++;
if(d3 >= d2) d3++;
if(d4 >= d1) d4++;
if(d4 >= d2) d4++;
if(d4 >= d3) d4++;
return d1*1000 + d2*100 + d3*10 + d4;
}
You could start with an integer number, 0x123456789, and pick random nibbles from it (the 4 bits that makes up one of the digits in the hex value). When a nibble has been selected, remove it from the number and continue picking from those left.
This makes exactly 4 calls to rand() and has no if or other conditions (other than the loop condition).
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int get_random_4digit() {
uint64_t bits = 0x123456789; // nibbles
int res = 0;
// pick random nibbles
for(unsigned last = 9 - 1; last > 9 - 1 - 4; --last) {
unsigned lsh = last * 4; // shift last nibble
unsigned sel = (rand() % (last + 1)) * 4; // shift for random nibble
// multiply with 10 and add the selected nibble
res = res * 10 + ((bits & (0xFULL << sel)) >> sel);
// move the last unselected nibble right to where the selected
// nibble was:
bits = (bits & ~(0xFULL << sel)) |
((bits & (0xFULL << lsh)) >> (lsh - sel));
}
return res;
}
Demo
Another variant could be to use the same value, 0x123456789, and do a Fisher-Yates shuffle on the nibbles. When the shuffle is done, return the 4 lowest nibbles. This is more expensive since it randomizes the order of all 9 nibbles - but it makes it easy if you want to select an arbitrary amount of them afterwards.
Example:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
uint16_t get_random_4digit() {
uint64_t bits = 0x123456789; // nibbles
// shuffle the nibbles
for(unsigned idx = 9 - 1; idx > 0; --idx) {
unsigned ish = idx * 4; // index shift
// shift for random nibble to swap with `idx`
unsigned swp = (rand() % (idx + 1)) * 4;
// extract the selected nibbles
uint64_t a = (bits & (0xFULL << ish)) >> ish;
uint64_t b = (bits & (0xFULL << swp)) >> swp;
// swap them
bits &= ~((0xFULL << ish) | (0xFULL << swp));
bits |= (a << swp) | (b << ish);
}
return bits & 0xFFFF; // return the 4 lowest nibbles
}
The bit manipulation can probably be optimized - but I wrote it like I thought it so it's probably better for readability to leave it as-is
You can then print the value as a hex value to get the output you want - or extract the 4 nibbles and convert it for decimal output.
int main() {
srand(time(NULL));
uint16_t res = get_random_4digit();
// print directly as hex:
printf("%X\n", res);
// or extract the nibbles and multiply to get decimal result - same output:
uint16_t a = (res >> 12) & 0xF;
uint16_t b = (res >> 8) & 0xF;
uint16_t c = (res >> 4) & 0xF;
uint16_t d = (res >> 0) & 0xF;
uint16_t dec = a * 1000 + b * 100 + c * 10 + d;
printf("%d\n", dec);
}
Demo
You should keep generating digits until distinct one found:
int get_random_4digit() {
int random_4digit = 0;
/* We must have 4 digits number - at least 1234 */
while (random_4digit < 1000) {
int digit = rand() % 9 + 1;
/* check if generated digit is not in the result */
for (int number = random_4digit; number > 0; number /= 10)
if (number % 10 == digit) {
digit = 0; /* digit has been found, we'll try once more */
break;
}
if (digit > 0) /* unique digit generated, we add it to result */
random_4digit = random_4digit * 10 + digit;
}
return random_4digit;
}
Please, fiddle youself
One way to do this is to create an array with all 9 digits, pick a random one and remove it from the list.
Something like this:
uint_fast8_t digits[]={1,2,3,4,5,6,7,8,9}; //only 1-9 are allowed, 0 is not allowed
uint_fast8_t left=4; //How many digits are left to create
unsigned result=0; //Store the 4-digit number here
while(left--)
{
uint_fast8_t digit=getRand(9-4+left); //pick a random index
result=result*10+digits[digit];
//Move all digits above the selcted one 1 index down.
//This removes the picked digit from the array.
while(digit<8)
{
digits[digit]=digits[digit+1];
digit++;
}
}
You said you need a solution without arrays. Luckily, we can store up to 16 4 bit numbers in a single uint64_t. Here is an example that uses a uint64_t to store the digit list so that no array is needed.
#include <stdint.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
unsigned getRand(unsigned max)
{
return rand()%(max+1);
}
//Creates a uint64_t that is used as an array.
//Use no more than 16 values and don't use values >0x0F
//The last argument will have index 0
uint64_t fakeArrayCreate(uint_fast8_t count, ...)
{
uint64_t result=0;
va_list args;
va_start (args, count);
while(count--)
{
result=(result<<4) | va_arg(args,int);
}
return result;
}
uint_fast8_t fakeArrayGet(uint64_t array, uint_fast8_t index)
{
return array>>(4*index)&0x0F;
}
uint64_t fakeArraySet(uint64_t array, uint_fast8_t index, uint_fast8_t value)
{
array = array & ~((uint64_t)0x0F<<(4*index));
array = array | ((uint64_t)value<<(4*index));
return array;
}
unsigned getRandomDigits(void)
{
uint64_t digits = fakeArrayCreate(9,9,8,7,6,5,4,3,2,1);
uint_fast8_t left=4;
unsigned result=0;
while(left--)
{
uint_fast8_t digit=getRand(9-4+left);
result=result*10+fakeArrayGet(digits,digit);
//Move all digits above the selcted one 1 index down.
//This removes the picked digit from the array.
while(digit<8)
{
digits=fakeArraySet(digits,digit,fakeArrayGet(digits,digit+1));
digit++;
}
}
return result;
}
//Test our function
int main(int argc, char **argv)
{
srand(atoi(argv[1]));
printf("%u\n",getRandomDigits());
}
You could use a partial Fisher-Yates shuffle on an array of 9 digits, stopping after 4 digits:
// Return random integer from 0 to n-1
// (for n in range 1 to RAND_MAX+1u).
int get_random_int(unsigned int n) {
unsigned int x = (RAND_MAX + 1u) / n;
unsigned int limit = x * n;
int s;
do {
s = rand();
} while (s >= limit);
return s / x;
}
// Return random 4-digit number from 1234 to 9876 with no
// duplicate digits and no 0 digit.
int get_random_4digit(void) {
char possible[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int result = 0;
int i;
// Uses partial Fisher-Yates shuffle.
for (i = 0; i < 4; i++) {
// Get random position rand_pos from remaining possibilities i to 8
// (positions before i contain previous selected digits).
int rand_pos = i + get_random_int(9 - i);
// Select digit from position rand_pos.
char digit = possible[rand_pos];
// Exchange digits at positions i and rand_pos.
possible[rand_pos] = possible[i];
possible[i] = digit; // not really needed
// Put selected digit into result.
result = result * 10 + digit;
}
return result;
}
EDIT: I forgot the requirement "while only using int's, if, while and functions, so no arrays etc.", so feel free to ignore this answer!
If normal C integer types are allowed including long long int, the get_random_4digit() function above can be replaced with the following to satisfy the requirement:
// Return random 4-digit number from 1234 to 9876 with no
// duplicate digits and no 0 digit.
int get_random_4digit(void) {
long long int possible = 0x123456789; // 4 bits per digit
int result = 0;
int i;
// Uses partial Fisher-Yates shuffle.
i = 0;
while (i < 4) {
// Determine random position rand_pos in remaining possibilities 0 to 8-i.
int rand_pos = get_random_int(9 - i);
// Select digit from position rand_pos.
int digit = (possible >> (4 * rand_pos)) & 0xF;
// Replace digit at position rand_pos with digit at position 0.
possible ^= ((possible ^ digit) & 0xF) << (4 * rand_pos);
// Shift remaining possible digits down one position.
possible >>= 4;
// Put selected digit into result.
result = result * 10 + digit;
i++;
}
return result;
}
There are multiple answers to this question already, but none of them seem to fit the requirement only using ints, if, while and functions. Here is a modified version of Pelle Evensen's simple solution:
#include <stdlib.h>
int get_random_4digit(void) {
int acc = 0, used = 0, i = 0;
while (i < 4) {
int idx = rand() % 9; // Not strictly uniform but never mind...
if (!(used & (1 << idx))) {
acc = acc * 10 + idx + 1;
used |= 1 << idx;
i++;
}
}
return acc;
}

Binary representation starting with a least significant bit in C

I'm trying to make a binary representation of an integer using binary() function and then use reverse() function to get bit reversal as can be seen below:
#include <stdio.h>
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
int binary(int n)
{
int b;
if (n == 0)
{
return 0;
}
else
{
b = (n % 2) + 10 * binary(n / 2);
unsigned char i = (unsigned char)b;
return reverse(i);
}
}
int main()
{
int n;
printf("Enter a decimal number: ");
scanf("%d", &n);
printf("The binary equivalent of %d is %d\n", n, binary(n));
return 0;
}
The issue I'm having is that I expect binary() to produce a binary number (for example, a binary representation fo 18 would be 10010), and then reverse() function to take this number and produce a reversed binary representation starting with the least significant bit (LSB) which should be 01001 in this case. However, when I try to run it, I get returned 0.
I'm new to C and I'm thinking maybe the issue is in the unsigned char datatype, but when, why if I convert b into unsigned char it still doesn't work?
When reversing the bits, all you have to do is check the LSB. Add that value to an output variable. Then shift the output variable by one to the left and shift the original number by one to the right. In the mathematical example below, I do a first 0 shift so it become easier on the eye with the formatting.
In your example of 10010:
Round 1: output = (00000 << 1) + (10010 & 1) = 00000
N = 10010 >> 1 = 01001
Round 2: output = (00000 << 1) + (01001 & 1) = 00001
N = 01001 >> 1 = 00100
Round 3: output = (00001 << 1) + (00100 & 1) = 00010
N = 00100 >> 1 = 00010
Round 4: output = (00010 << 1) + (0010 & 1) = 00100
N = 00010 >> 1 = 00001
Round 5: output = (00100 << 1) + (00001 & 1) = 01001
N = 00001 >> 1 = 00000
Example:
#include <stdio.h>
int binary(int n)
{
int output = 0;
if ( n == 0 ) return 0;
// Save one left shift
output += n & 1;
n = n >> 1;
while( n != 0 ){
output = output << 1;
output += n & 1;
n = n >> 1;
printf("%d\n", output);
}
return output;
}
void printBin(int n){
char bin[33] = {0};
for (int i = 31; i > -1; i-- ){
bin[i] = (char)((n & 1) ^ 48);
n = n >> 1;
}
puts(bin);
}
int main()
{
int n; int rb;
printf("Enter a decimal number: ");
scanf("%d", &n);
rb = binary(n);
printf("The binary equivalent of %d is %d\n", n, rb);
printf("%11d:", n);
printBin(n);
printf("%11d:", rb);
printBin(rb);
return 0;
}

Long long int makes my Sieve of Eratosthenes super slow?

I have a program that requires me to find primes up till 10**10-1 (10,000,000,000). I wrote a Sieve of Eratosthenes to do this, and it worked very well (and accurately) as high as 10**9 (1,000,000,000). I confirmed its accuracy by having it count the number of primes it found, and it matched the value of 50,847,534 on the chart found here. I used unsigned int as the storage type and it successfully found all the primes in approximately 30 seconds.
However, 10**10 requires that I use a larger storage type: long long int. Once I switched to this, the program is running signifigantly slower (its been 3 hours plus and its still working). Here is the relevant code:
typedef unsigned long long ul_long;
typedef unsigned int u_int;
ul_long max = 10000000000;
u_int blocks = 1250000000;
char memField[1250000000];
char mapBit(char place) { //convert 0->0x80, 1->0x40, 2->0x20, and so on
return 0x80 >> (place);
}
for (u_int i = 2; i*i < max; i++) {
if (memField[i / 8] & activeBit) { //Use correct memory block
for (ul_long n = 2 * i; n < max; n += i) {
char secondaryBit = mapBit(n % 8); //Determine bit position of n
u_int activeByte = n / 8; //Determine correct memory block
if (n < 8) { //Manual override memory block and bit for first block
secondaryBit = mapBit(n);
activeByte = 0;
}
memField[activeByte] &= ~(secondaryBit); //Set the flag to false
}
}
activeBit = activeBit >> 1; //Check the next
if (activeBit == 0x00) activeBit = 0x80;
}
I figure that since 10**10 is 10x larger then 10**9 it should take 10 times the amount of time. Where is the flaw in this? Why did changing to long long cause such significant performance issues and how can I fix this? I recognize that the numbers get larger, so it should be somewhat slower, but only towards the end. Is there something I'm missing.
Note: I realize long int should technically be large enough but my limits.h says it isn't even though I'm compiling 64 bit. Thats why I use long long int in case anyone was wondering. Also, keep in mind, I have no computer science training, just a hobbyist.
edit: just ran it in "Release" as x86-64 with some of the debug statements suggested. I got the following output:
looks like I hit the u_int bound. I don't know why i is getting that large.
Your program has an infinite loop in for (u_int i = 2; i*i < max; i++). i is an unsigned int so i*i wraps at 32-bit and is always less than max. Make i an ul_long.
Note that you should use simpler bit pattern from 1 to 0x80 for bit 0 to 7.
Here is a complete version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned long long ul_long;
typedef unsigned int u_int;
#define TESTBIT(a, bit) (a[(bit) / 8] & (1 << ((bit) & 7)))
#define CLEARBIT(a, bit) (a[(bit) / 8] &= ~(1 << ((bit) & 7)))
ul_long count_primes(ul_long max) {
size_t blocks = (max + 7) / 8;
unsigned char *memField = malloc(blocks);
if (memField == NULL) {
printf("cannot allocate memory for %llu bytes\n",
(unsigned long long)blocks);
return 0;
}
memset(memField, 255, blocks);
CLEARBIT(memField, 0); // 0 is not prime
CLEARBIT(memField, 1); // 1 is not prime
// clear bits after max
for (ul_long i = max + 1; i < blocks * 8ULL; i++) {
CLEARBIT(memField, i);
}
for (ul_long i = 2; i * i < max; i++) {
if (TESTBIT(memField, i)) { //Check if i is prime
for (ul_long n = 2 * i; n < max; n += i) {
CLEARBIT(memField, n); //Reset all multiples of i
}
}
}
unsigned int bitCount[256];
for (int i = 0; i < 256; i++) {
bitCount[i] = (((i >> 0) & 1) + ((i >> 1) & 1) +
((i >> 2) & 1) + ((i >> 3) & 1) +
((i >> 4) & 1) + ((i >> 5) & 1) +
((i >> 6) & 1) + ((i >> 7) & 1));
}
ul_long count = 0;
for (size_t i = 0; i < blocks; i++) {
count += bitCount[memField[i]];
}
printf("count of primes up to %llu: %llu\n", max, count);
free(memField);
return count;
}
int main(int argc, char *argv[]) {
if (argc > 1) {
for (int i = 1; i < argc; i++) {
count_primes(strtoull(argv[i], NULL, 0));
}
} else {
count_primes(10000000000);
}
return 0;
}
It completes in 10 seconds for 10^9 and 131 seconds for 10^10:
count of primes up to 1000000000: 50847534
count of primes up to 10000000000: 455052511

Listing prime numbers using Sieve's method using bitmask

I wrote the following code to list all the prime numbers upto 2 billion using Sieve's method. I used bitmasking for flagging purpose. While I am able to get the prime numbers correctly, a few primes in the beginning are missing every time. Please help me find the bug in the program.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX 2000000000
char* listPrimes(){
int block = sqrt(MAX);
char* mark = calloc((MAX/8),sizeof(char));
int i = 2;
int j;
char mask[8];
for(j=0;j<8;j++)
mask[j] = 0;
mask[7] = 1;
mask[6] |= mask[7] << 1;
mask[5] |= mask[7] << 2;
mask[4] |= mask[7] << 3;
mask[3] |= mask[7] << 4;
mask[2] |= mask[7] << 5;
mask[1] |= mask[7] << 6;
mask[0] |= mask[7] << 7;
for(j=0;j<8;j++)
printf("%d ",mask[j]);
mark[0] |= mask[0];
mark[0] |= mask[1];
while (i < block){
for (j = 2; i*j <= block; j++)
mark[(i*j) / 8] |= mask[((i*j) % 8 )];
i++;
}
printf("\n");
printf("The block size is\t:\t%d\n",block);
j = 2;
while(j<=block){
if((mark[j / 8] & mask[j]) == 0 ){
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
mark[i / 8] |= mask[(i % 8)];
}
}
}
while((mark[++j / 8] & mask[j % 8]) != 0);
}
for(j=0;j<=MAX;j++)
if((mark[j / 8] & mask[(j % 8)]) == 0)
printf("%d\n", ((8*(j / 8)) + (j % 8)));
return mark;
}
int main(int argc,char* argv[]){
listPrimes();
return 0;
}
As ArunMK said, in the second while loop you mark the prime j itself as a multiple of j. And as Lee Meador said, you need to take the modulus of j modulo 8 for the mask index, otherwise you access out of bounds and invoke undefined behaviour.
A further point where you invoke undefined behaviour is
while((mark[++j / 8] & mask[j % 8]) != 0);
where you use and modify j without intervening sequence point. You can avoid that by writing
do {
++j;
}while((mark[j/8] & mask[j%8]) != 0);
or, if you insist on a while loop with empty body
while(++j, (mark[j/8] & mask[j%8]) != 0);
you can use the comma operator.
More undefined behaviour by accessing mark[MAX/8] which is not allocated in
for(i = 2;i <= MAX; i++){
and
for(j=0;j<=MAX;j++)
Also, if char is signed and eight bits wide,
mask[0] |= mask[7] << 7;
is implementation-defined (and may raise an implementation-defined signal) since the result of
mask[0] | (mask[7] << 7)
(the int 128) is not representable as a char.
But why are you dividing each number by all primes not exceeding the square root of the bound in the second while loop?
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
That makes your algorithm not a Sieve of Eratosthenes, but a trial division.
Why don't you use the technique from the first while loop there too? (And then, why two loops at all?)
while (i <= block){
if ((mark[i/8] & mask[i%8]) == 0) {
for (j = 2; i*j < MAX; j++) {
mark[(i*j) / 8] |= mask[((i*j) % 8 )];
}
}
i++;
}
would not overflow (for the given value of MAX, if that is representable as an int), and produce the correct output orders of magnitude faster.
Change the middle loop to add the modulo:
j = 2;
while(j<=block){
if((mark[j / 8] & mask[j % 8]) == 0 ){
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
mark[i / 8] |= mask[(i % 8)];
}
}
}
}
In the second while loop you are looping through i from 2 onwards and you do an if (i%j == 0). This will be true for i when it is a prime as well. You need to check for (i != j). Also the modulo as reported above. Hence it becomes:
if ((i%j == 0) {
if (i!=j)
mark[i/j] |= mask[i%j];
}

How do I get bit-by-bit data from an integer value in C?

I want to extract bits of a decimal number.
For example, 7 is binary 0111, and I want to get 0 1 1 1 all bits stored in bool. How can I do so?
OK, a loop is not a good option, can I do something else for this?
If you want the k-th bit of n, then do
(n & ( 1 << k )) >> k
Here we create a mask, apply the mask to n, and then right shift the masked value to get just the bit we want. We could write it out more fully as:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
You can read more about bit-masking here.
Here is a program:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
As requested, I decided to extend my comment on forefinger's answer to a full-fledged answer. Although his answer is correct, it is needlessly complex. Furthermore all current answers use signed ints to represent the values. This is dangerous, as right-shifting of negative values is implementation-defined (i.e. not portable) and left-shifting can lead to undefined behavior (see this question).
By right-shifting the desired bit into the least significant bit position, masking can be done with 1. No need to compute a new mask value for each bit.
(n >> k) & 1
As a complete program, computing (and subsequently printing) an array of single bit values:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
Assuming that you want to calculate all bits as in this case, and not a specific one, the loop can be further changed to
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
This modifies input in place and thereby allows the use of a constant width, single-bit shift, which may be more efficient on some architectures.
Here's one way to do it—there are many others:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
It is hard to understand why use of a loop is not desired, but it is easy enough to unroll the loop:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
Or evaluating constant expressions in the last four statements:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
Here's a very simple way to do it;
int main()
{
int s=7,l=1;
vector <bool> v;
v.clear();
while (l <= 4)
{
v.push_back(s%2);
s /= 2;
l++;
}
for (l=(v.size()-1); l >= 0; l--)
{
cout<<v[l]<<" ";
}
return 0;
}
Using std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
#prateek thank you for your help. I rewrote the function with comments for use in a program. Increase 8 for more bits (up to 32 for an integer).
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
#include <stdio.h>
int main(void)
{
int number = 7; /* signed */
int vbool[8 * sizeof(int)];
int i;
for (i = 0; i < 8 * sizeof(int); i++)
{
vbool[i] = number<<i < 0;
printf("%d", vbool[i]);
}
return 0;
}
If you don't want any loops, you'll have to write it out:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
As demonstrated here, this also works in an initializer.

Resources