Does rand() function in C have a limit? - c

Here is a sample code
int x = rand() % 90000;
When I was doing something like this I realized all the numbers were around 0 - 30000.
Is there a limit for this? If there is how can I use it without limits?

You should not use rand(), because it is quite poor in many C standard library implementations. It will return a pseudorandom number between 0 and RAND_MAX, inclusive, but RAND_MAX is often relatively small; for example, 32767.
Using the modulo operator to yield a range of integers is problematic if the range is a large fraction of the range of values the generator function can return, because the distribution is not exactly uniform.
For example, let's say RAND_MAX is 59999, and we used rand() % 40000. The probability of the result being between 0 and 19999 is 67%, but only 33% between 20000 and 39999. This is because that rand() produces a value in [0,19999] at 1/3 probability, [20000,39999] at 1/3 probability, and [40000..59999] at 1/3 probability; but that last third folds back so that it yields [0,19999] after the modulo operation!
For small ranges the bias is not so noticeable.
Personally, I like to generate enough random bits to cover the desired range, then use the exclusion method to pick the value.
If we need to use rand(), we can use the following helper function to generate a pseudorandom number whose range is at least atleast (but may be larger; i.e. it can return a larger value):
#include <inttypes.h>
static inline uint64_t rand_atleast(uint64_t atleast)
{
uint64_t result = 0;
do {
result = ((uint64_t)RAND_MAX + 1) * result + (uint64_t)rand();
atleast /= ((uint64_t)RAND_MAX + 1);
} while (atleast > 0);
return result;
}
To use the exclusion method to create ints within a desired range, we can use a structure to contain the stuff we need, a helper function to initialize that range (to describe some specific range of ints), and another helper function to generate integers within that range:
struct range_spec {
uint64_t mask;
uint64_t limit;
int base;
};
static inline void set_range(struct range_spec *spec,
int minimum, int maximum)
{
uint64_t mask;
int base;
if (minimum <= maximum) {
base = minimum;
mask = maximum - minimum;
} else {
base = maximum;
mask = minimum - maximum;
}
spec->base = base;
spec->limit = mask;
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
mask |= mask >> 32;
spec->mask = mask;
}
static inline int rand_range(const struct range_spec *spec)
{
const uint64_t mask = spec->mask;
const uint64_t limit = spec->limit;
uint64_t result;
do {
result = rand_atleast(mask) & mask;
} while (result > limit);
return spec->base + result;
}
However, this is a lot of work to get pretty poor pseudorandom numbers: not worth it in my opinion.
I usually use Xorshift64* instead. It is fast, quite random (see this extended comment of mine), and really easy to implement.
Essentially, you can use a small header file, say rng64.h:
#ifndef RNG64_H
#define RNG64_H
#include <inttypes.h>
#include <time.h>
typedef struct {
uint64_t limit;
int64_t base;
int shift;
} rng64_intrange_spec;
static uint64_t rng64_state = 1;
static inline uint64_t rng64(void)
{
uint64_t x = rng64_state;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
rng64_state = x;
return x * UINT64_C(2685821657736338717);
}
static inline uint64_t rng64_randomize(void)
{
uint64_t x;
int n = 1000;
x = ((uint64_t)time(NULL) * UINT64_C(19076794157513))
^ ((uint64_t)clock() * UINT64_C(809712647));
if (!x)
x = 1;
while (n-->0) {
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
}
rng64_state = x;
return x;
}
static inline double rng64_one(void)
{
return (double)rng64() / 18446744073709551616.0;
}
static inline int64_t rng64_intrange(rng64_intrange_spec *spec)
{
const uint64_t limit = spec->limit;
const int shift = spec->shift;
uint64_t value;
do {
value = rng64() >> shift;
} while (value > limit);
return spec->base + value;
}
static inline void rng64_set_intrange(rng64_intrange_spec *spec,
int64_t minimum,
int64_t maximum)
{
int64_t base;
uint64_t limit;
int bits = 0;
if (minimum <= maximum) {
base = minimum;
limit = maximum - minimum;
} else {
base = maximum;
limit = minimum - maximum;
}
spec->base = base;
spec->limit = limit;
while (limit >= 32768) {
limit >>= 16;
bits += 16;
}
while (limit >= 8) {
limit >>= 4;
bits += 4;
}
while (limit > 0) {
limit >>= 1;
bits += 1;
}
spec->shift = 64 - bits;
}
#endif /* RNG64_H */
Somewhere near the beginning of your program, call rng64_randomize() to generate a state based on the current time (wall clock via time(), and CPU time used to execute the current process via clock()). The initial state is churned a bit, to ensure you don't get similar sequences when running the code in quick succession. You can set the rng64_state to any value except zero, to generate a specific sequence. (Zero state will generate only zeroes.) I recommend using
printf("Using %" PRIu64 " as the Xorshift64* random number seed.\n", rng64_randomize());
which prints both the seed, and the pseudorandom number generator algorithm used, near the beginning of the program. That allows someone to reproduce the test (by setting rng64_state to that value instead of calling rng64_randomize(), or reimplement the test using their own equivalent code). Reproducibility is good.
While (uint64_t)time(NULL) is not guaranteed to work by the C standard, it does work in all current widely-used C implementations I am aware of.
If you want to compare to a different pseudorandom number generator, just reimplement another using a similar header file, and include that instead. That way you don't need to change any code that uses the generator, only the generator code itself.
rng_one() returns uniform pseudorandom numbers between 0 and 1.0, inclusive. If you want the upper limit to be exclusive, use e.g.
static inline double rng64_one(void)
{
double r;
do {
r = (double)rng64() / 18446744073709551616.0;
} while (r >= 1.0);
return r;
}
and if both limits exclusive (so it never returns 0.0 or 1.0 exactly), while (r <= 0.0 || r >= 1.0); instead.
Here's an example of how to use the rng64.h above:
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include "rng64.h"
int main(int argc, char *argv[])
{
rng64_intrange_spec r;
int minval, maxval, count, i;
char dummy;
if (argc != 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s MIN MAX COUNT\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This program outputs COUNT pseudorandom integers,\n");
fprintf(stderr, "between MIN and MAX, inclusive.\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
if (sscanf(argv[1], " %d %c", &minval, &dummy) != 1) {
fprintf(stderr, "%s: Invalid minimum.\n", argv[1]);
return EXIT_FAILURE;
}
if (sscanf(argv[2], " %d %c", &maxval, &dummy) != 1 || maxval < minval) {
fprintf(stderr, "%s: Invalid maximum.\n", argv[2]);
return EXIT_FAILURE;
}
if (sscanf(argv[3], " %d %c", &count, &dummy) != 1 || count < 0) {
fprintf(stderr, "%s: Invalid count.\n", argv[3]);
return EXIT_FAILURE;
}
fprintf(stderr, "Generating %d pseudorandom integers in [%d, %d],\n", count, minval, maxval);
fprintf(stderr, "using Xorshift64* with seed %" PRIu64 ".\n", rng64_randomize());
fflush(stderr);
rng64_set_intrange(&r, minval, maxval);
for (i = 0; i < count; i++)
printf("%d\n", (int)rng64_intrange(&r));
return EXIT_SUCCESS;
}
Specify the minimum and maximum values (integers), and the number of integers to output, as command-line parameters.

Related

How to correctly implement multiply for floating point numbers (software FP)

My program is about a method which is given floats and in this method I want to multiply or add those floats. But not multiply like a * b, I want to break those floats down to their structure like the bit for the sign, the 8 bit for the exponent and the rest of the bits as the mantissa.
I want to implement / emulate software floating-point add and multiply (to learn more about what FP hardware has to do).
In the head of the program there are the breakdowns:
#define SIGN(x) (x>>31);
#define MANT(x) (x&0x7FFFFF);
#define EXPO(x) ((x>>23)&0xFF);
#define SPLIT(x, s, m, e) do { \
s = SIGN(x); \
m = MANT(x); \
e = EXPO(x); \
if ( e != 0x00 && e != 0xFF ) { \
m |= 0x800000; \
} \
} while ( 0 )
#define BUILD(x, s, m, e) do { \
x = (s << 31) | (e<<23) | (m&0x7FFFFF); \
} while ( 0 )
The main looks as follows:
float f = 2.3;
float g = 1.8;
float h = foo(&f, &g);
And the method for the calculation looks like:
float foo(float *a, float *b) {
uint32_t ia = *(unsigned int *)a;
uint32_t ib = *(unsigned int *)b;
uint32_t result = 0;
uint32_t signa, signb, signr;
uint32_t manta, mantb, mantr;
uint32_t expoa, expob, expor;
SPLIT(ia, signa, manta, expoa);
SPLIT(ib, signb, mantb, expob);
I already tried the multiply by adding the exponents and multiply their mantissas as follow:
expor = (expoa -127) + (expob -127) + 127;
mantr = (manta) * (mantb);
signr = signa ^ signb;
The return and rebuild of the new float:
BUILD(result, signr, mantr, expor);
return *(float *)&result;
The problem is now, that the result is wrong. the mantr even takes a very low negative Number (in case if foo gets 1.5 and 2.4 mantr takes -838860800 and the result is 2.0000000).
You can't just take truncate the result of the mantissa multiply, you need to take the top 24 bits (after using the low half for rounding) and renormalize (adjust the exponent).
Floating point operations keep the top significand bits. The most significant part of the integer product is the high bits; the low bits are further places after the decimal. (Terminology: it's a "binary point", not "decimal point", because binary floats use radix 2 (binary), not 10 (decimal).)
For normalized inputs, the implicit leading 1 in the input significands means the 32x32 => 64-bit uint64_t product that you use to implement 24 x 24 => 48-bit mantissa multiplication will have its high bit in one of 2 possible locations, so you don't need a bit-scan to find it. A compare or single-bit-test will do.
For subnormal inputs, that's not guaranteed so you need to check where the MSB is, e.g. with GNU C __builtin_clzll. (There are many special cases to handle for one or both inputs being subnormal, and/or the output being subnormal.)
See https://en.wikipedia.org/wiki/Single-precision_floating-point_format for more about the IEEE-754 binary32 format, including the implied leading 1 of the significand.
And see #njuffa's answer for an actual tested + working implementation that does 64-bit operations as two 32-bit halves for some reason, instead of letting C do that efficiently.
Also, return *(float *)&result; violates strict aliasing. It's only safe on MSVC. Use a union or memcpy for type punning in C99 / C11.
Emulating the multiplication of two IEEE-754 (2008) binary32 operands is a bit more complex than the question suggests. In general, we have to distinguish the following operand classes: zeros, subnormals (0 < |x| < 2-126), normals (2126 ≤ |x| < 2128), infinities, NaNs. Normals use biased exponents in [1, 254], while any of the special operand classes use biased exponents in {0, 255}. The following assumes we want to implement floating-point multiply with all floating-point exceptions masked, and using the round-to-nearest-to-even rounding mode.
First, we check whether any of the arguments belongs to a special operand class. If so, we check the special cases in sequence. If one of the arguments is a NaN, we turn that NaN into a QNaN and return it. If one of the operands is zero, we return an appropriately signed zero, unless the other argument is an infinity, in which case we return a special QNaN INDEFINITE since this is an invalid operation. After that we check for any argument of infinity, returning an appropriately signed infinity. This leaves subnormals, which we normalize. In case there are two subnormal arguments, we only need to normalize one of them as the result will underflow to zero.
The multiplication of normals proceeds as the asker envisioned in the question. The sign of the result is the exclusive-OR of the signs of the arguments, the exponent of the result is the sum of the exponents of the arguments (adjusted for exponent bias), and the significand of the result is generated from the product of the significant of the arguments. We need the full product for rounding. We can either use a 64-bit type for that, or represent it with a pair of 32-bit numbers. In the code below I have chose the latter representation. Rounding to nearest-or-even is straightforward: if we have a tie-case (the result is exactly in the middle between the closest two binary32 number), we need to round up if the least significant bit of the mantissa is 1. Otherwise, we need to round up if the most significant discarded bit (the round bit) is 1.
Three cases need to be considered for the result, based on the result exponent prior to rounding: Exponent is in normal range, result overflows (too large in magnitude), or it underflows (too small in magnitude). In the first case, the result is a normal or infinity if overflow occurs during rounding. In the second case, the result is infinity. In the last case the result is either zero (severe underflow), a subnormal, or the smallest normal (if round-up occurs).
The following code, with a simple framework for light testing via gobs of random test cases and several thousand interesting patterns shows an exemplary ISO-C implementation written in a couple of hours for reasonable clarity and reasonable performance. I let the test framework run for an hour or so on an x64 platform and no errors were reported. If you plan to use the code in production, you would want to construct a more stringent test framework, and may need additional performance tuning.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#define FLOAT_MANT_BITS (23)
#define FLOAT_EXPO_BITS (8)
#define FLOAT_EXPO_BIAS (127)
#define FLOAT_MANT_MASK (~((~0u) << (FLOAT_MANT_BITS+1))) /* incl. integer bit */
#define EXPO_ADJUST (1) /* adjustment for performance reasons */
#define MIN_NORM_EXPO (1) /* minimum biased exponent of normals */
#define MAX_NORM_EXPO (254) /* maximum biased exponent of normals */
#define INF_EXPO (255) /* biased exponent of infinities */
#define EXPO_MASK (~((~0u) << FLOAT_EXPO_BITS))
#define FLOAT_SIGN_MASK (0x80000000u)
#define FLOAT_IMPLICIT_BIT (1 << FLOAT_MANT_BITS)
#define RND_BIT_SHIFT (31)
#define RND_BIT_MASK (1u << RND_BIT_SHIFT)
#define FLOAT_INFINITY (0x7f800000)
#define FLOAT_INDEFINITE (0xffc00000u)
#define MANT_LSB (0x00000001)
#define FLOAT_QNAN_BIT (0x00400000)
#define MAX_SHIFT (FLOAT_MANT_BITS + 2)
uint32_t fp32_mul_core (uint32_t a, uint32_t b)
{
uint64_t prod;
uint32_t expoa, expob, manta, mantb, shift;
uint32_t r, signr, expor, mantr_hi, mantr_lo;
/* split arguments into sign, exponent, significand */
expoa = ((a >> FLOAT_MANT_BITS) & EXPO_MASK) - EXPO_ADJUST;
expob = ((b >> FLOAT_MANT_BITS) & EXPO_MASK) - EXPO_ADJUST;
manta = (a | FLOAT_IMPLICIT_BIT) & FLOAT_MANT_MASK;
mantb = (b | FLOAT_IMPLICIT_BIT) & FLOAT_MANT_MASK;
/* result sign bit: XOR sign argument signs */
signr = (a ^ b) & FLOAT_SIGN_MASK;
if ((expoa >= (MAX_NORM_EXPO - EXPO_ADJUST)) || /* at least one argument is special */
(expob >= (MAX_NORM_EXPO - EXPO_ADJUST))) {
if ((a & ~FLOAT_SIGN_MASK) > FLOAT_INFINITY) { /* a is NaN */
/* return quietened NaN */
return a | FLOAT_QNAN_BIT;
}
if ((b & ~FLOAT_SIGN_MASK) > FLOAT_INFINITY) { /* b is NaN */
/* return quietened NaN */
return b | FLOAT_QNAN_BIT;
}
if ((a & ~FLOAT_SIGN_MASK) == 0) { /* a is zero */
/* return NaN if b is infinity, else zero */
return (expob != (INF_EXPO - EXPO_ADJUST)) ? signr : FLOAT_INDEFINITE;
}
if ((b & ~FLOAT_SIGN_MASK) == 0) { /* b is zero */
/* return NaN if a is infinity, else zero */
return (expoa != (INF_EXPO - EXPO_ADJUST)) ? signr : FLOAT_INDEFINITE;
}
if (((a & ~FLOAT_SIGN_MASK) == FLOAT_INFINITY) || /* a or b infinity */
((b & ~FLOAT_SIGN_MASK) == FLOAT_INFINITY)) {
return signr | FLOAT_INFINITY;
}
if ((int32_t)expoa < (MIN_NORM_EXPO - EXPO_ADJUST)) { /* a is subnormal */
/* normalize significand of a */
manta = a & FLOAT_MANT_MASK;
expoa++;
do {
manta = 2 * manta;
expoa--;
} while (manta < FLOAT_IMPLICIT_BIT);
} else if ((int32_t)expob < (MIN_NORM_EXPO - EXPO_ADJUST)) { /* b is subnormal */
/* normalize significand of b */
mantb = b & FLOAT_MANT_MASK;
expob++;
do {
mantb = 2 * mantb;
expob--;
} while (mantb < FLOAT_IMPLICIT_BIT);
}
}
/* result exponent: add argument exponents and adjust for biasing */
expor = expoa + expob - FLOAT_EXPO_BIAS + 2 * EXPO_ADJUST;
mantb = mantb << FLOAT_EXPO_BITS; /* preshift to align result signficand */
/* result significand: multiply argument signficands */
prod = (uint64_t)manta * mantb;
mantr_hi = (uint32_t)(prod >> 32);
mantr_lo = (uint32_t)(prod >> 0);
/* normalize significand */
if (mantr_hi < FLOAT_IMPLICIT_BIT) {
mantr_hi = (mantr_hi << 1) | (mantr_lo >> (32 - 1));
mantr_lo = (mantr_lo << 1);
expor--;
}
if (expor <= (MAX_NORM_EXPO - EXPO_ADJUST)) { /* normal, may overflow to infinity during rounding */
/* combine biased exponent, sign and signficand */
r = (expor << FLOAT_MANT_BITS) + signr + mantr_hi;
/* round result to nearest or even; overflow to infinity possible */
r = r + ((mantr_lo == RND_BIT_MASK) ? (mantr_hi & MANT_LSB) : (mantr_lo >> RND_BIT_SHIFT));
} else if ((int32_t)expor > (MAX_NORM_EXPO - EXPO_ADJUST)) { /* overflow */
/* return infinity */
r = signr | FLOAT_INFINITY;
} else { /* underflow */
/* return zero, normal, or smallest subnormal */
shift = 0 - expor;
if (shift > MAX_SHIFT) shift = MAX_SHIFT;
/* denormalize significand */
mantr_lo = mantr_hi << (32 - shift) | (mantr_lo ? 1 : 0);
mantr_hi = mantr_hi >> shift;
/* combine sign and signficand; biased exponent known to be zero */
r = mantr_hi + signr;
/* round result to nearest or even */
r = r + ((mantr_lo == RND_BIT_MASK) ? (mantr_hi & MANT_LSB) : (mantr_lo >> RND_BIT_SHIFT));
}
return r;
}
uint32_t float_as_uint (float a)
{
uint32_t r;
memcpy (&r, &a, sizeof r);
return r;
}
float uint_as_float (uint32_t a)
{
float r;
memcpy (&r, &a, sizeof r);
return r;
}
float fp32_mul (float a, float b)
{
return uint_as_float (fp32_mul_core (float_as_uint (a), float_as_uint (b)));
}
/* Fixes via: Greg Rose, KISS: A Bit Too Simple. http://eprint.iacr.org/2011/007 */
static unsigned int z=362436069,w=521288629,jsr=362436069,jcong=123456789;
#define znew (z=36969*(z&0xffff)+(z>>16))
#define wnew (w=18000*(w&0xffff)+(w>>16))
#define MWC ((znew<<16)+wnew)
#define SHR3 (jsr^=(jsr<<13),jsr^=(jsr>>17),jsr^=(jsr<<5)) /* 2^32-1 */
#define CONG (jcong=69069*jcong+13579) /* 2^32 */
#define KISS ((MWC^CONG)+SHR3)
#define ISNAN(x) ((float_as_uint (x) << 1) > 0xff000000)
#define QNAN(x) (x | FLOAT_QNAN_BIT)
#define PURELY_RANDOM (0)
#define PATTERN_BASED (1)
#define TEST_MODE (PURELY_RANDOM)
uint32_t v[8192];
int main (void)
{
unsigned long long count = 0;
float a, b, res, ref;
uint32_t i, j, patterns, idx = 0, nbrBits = sizeof (uint32_t) * CHAR_BIT;
/* pattern class 1: 2**i */
for (i = 0; i < nbrBits; i++) {
v [idx] = ((uint32_t)1 << i);
idx++;
}
/* pattern class 2: 2**i-1 */
for (i = 0; i < nbrBits; i++) {
v [idx] = (((uint32_t)1 << i) - 1);
idx++;
}
/* pattern class 3: 2**i+1 */
for (i = 0; i < nbrBits; i++) {
v [idx] = (((uint32_t)1 << i) + 1);
idx++;
}
/* pattern class 4: 2**i + 2**j */
for (i = 0; i < nbrBits; i++) {
for (j = 0; j < nbrBits; j++) {
v [idx] = (((uint32_t)1 << i) + ((uint32_t)1 << j));
idx++;
}
}
/* pattern class 5: 2**i - 2**j */
for (i = 0; i < nbrBits; i++) {
for (j = 0; j < nbrBits; j++) {
v [idx] = (((uint32_t)1 << i) - ((uint32_t)1 << j));
idx++;
}
}
/* pattern class 6: MAX_UINT/(2**i+1) rep. blocks of i zeros an i ones */
for (i = 0; i < nbrBits; i++) {
v [idx] = ((~(uint32_t)0) / (((uint32_t)1 << i) + 1));
idx++;
}
patterns = idx;
/* pattern class 6: one's complement of pattern classes 1 through 5 */
for (i = 0; i < patterns; i++) {
v [idx] = ~v [i];
idx++;
}
/* pattern class 7: two's complement of pattern classes 1 through 5 */
for (i = 0; i < patterns; i++) {
v [idx] = ~v [i] + 1;
idx++;
}
patterns = idx;
#if TEST_MODE == PURELY_RANDOM
printf ("using purely random test vectors\n");
#elif TEST_MODE == PATTERN_BASED
printf ("using pattern-based test vectors\n");
printf ("#patterns = %u\n", patterns);
#endif // TEST_MODE
do {
#if TEST_MODE == PURELY_RANDOM
a = uint_as_float (KISS);
b = uint_as_float (KISS);
#elif TEST_MODE == PATTERN_BASED
i = KISS % patterns;
j = KISS % patterns;
a = uint_as_float ((v[i] & 0x7fffff) | (KISS & ~0x7fffff));
b = uint_as_float ((v[j] & 0x7fffff) | (KISS & ~0x7fffff));
#endif // TEST_MODE
res = fp32_mul (a, b);
ref = a * b;
/* check for bit pattern mismatch between result and reference */
if (float_as_uint (res) != float_as_uint (ref)) {
/* if both a and b are NaNs, either could be returned quietened */
if (! (ISNAN (a) && ISNAN (b) &&
((QNAN (float_as_uint (a)) == float_as_uint (res)) ||
(QNAN (float_as_uint (b)) == float_as_uint (res))))) {
printf ("err: a=% 15.8e (%08x) b=% 15.8e (%08x) res=% 15.8e (%08x) ref=%15.8e (%08x)\n",
a, float_as_uint(a), b, float_as_uint (b), res, float_as_uint (res), ref, float_as_uint (ref));
return EXIT_FAILURE;
}
}
count++;
if (!(count & 0xffffff)) printf ("\r%llu", count);
} while (1);
return EXIT_SUCCESS;
}
It is much more complicated. Take a look on the source of the softmath library (for example https://github.com/riscv/riscv-pk/blob/master/softfloat/f64_mul.c). Clone it and analyze.

C - BitArray Segmentation Fault

I'm currently trying to implement the Sieve of Eratosthenes in C using a BitSet, but I get a segmentation fault, when I try to sieve the primes up to 1,000,000 (1 million) - 100,000 (100 thousand) is still working though and I can't figure out why I get the seg-fault.
This is the code I use (I marked the line, in which the error occurs):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
void eSieve(uint64_t upperLimit);
int main(int argc, char *argv[]) {
uint64_t upperLimit;
if (argc == 2) {
upperLimit = (uint64_t) atoll(argv[1]);
printf("Using custom limit: %" PRIu64 "\n", upperLimit);
} else {
upperLimit = 1000;
printf("Using default limit: %" PRIu64 "\n", upperLimit);
}
eSieve(upperLimit);
return 0;
}
typedef uint32_t prime_t;
void eSieve(uint64_t upperLimit) {
if (upperLimit < 2) {
printf("FAILURE: Bad upper limit.\n");
return;
}
prime_t *sieve = calloc(1, (upperLimit + sizeof(prime_t) - 1)/sizeof(prime_t));
if (!sieve) {
printf("FAILURE: Could not initialize sieve.\n");
return;
}
sieve[0] |= 3; // Set first and second bit (representing 0 and 1)
uint64_t prime, number;
for (prime = 2; prime * prime < upperLimit; ) {
for (number = prime * prime; number < upperLimit; number += prime) {
// Segmentation fault for prime = 2 and number = 258048
sieve[number/sizeof(prime_t)] |= (((prime_t) 1) << (number % sizeof(prime_t)));
}
while ((sieve[++prime/sizeof(prime_t)] & (prime_t)1 << (prime % sizeof(prime_t))) != 0)
;
}
number = upperLimit;
while ((sieve[--number/sizeof(prime_t)] & (((prime_t)1) << (number % sizeof(prime_t)))) != 0)
;
printf("Greatest prime-number below %" PRIu64 ": %" PRIu64 "\n",
upperLimit, number);
}
Does anybody know why the error occurs? I'm guessing that now enough space is allocated (somehow), but I can't see how this would be possible at the moment...
You're not getting the correct bit number:
sieve[number/sizeof(prime_t)] |= (((prime_t) 1) << (number % sizeof(prime_t)));
When you do the division and mod, you need to divide/mod by the number of bits, not the number of bytes:
sieve[number/(sizeof(prime_t)*8)] |= (((prime_t) 1) << (number % (sizeof(prime_t)*8)));
And similarly:
while ((sieve[++prime/(sizeof(prime_t)*8)] & (prime_t)1 << (prime % (sizeof(prime_t)*8))) != 0)
...
while ((sieve[--number/(sizeof(prime_t)*8)] & (((prime_t)1) << (number % (sizeof(prime_t)*8)))) != 0)
EDIT:
You're also not allocating the right amount of memory. You need a number of bytes equal to the limit divided by the number of bits, plus 1 sizeof(prime_t) to round up.
prime_t *sieve = calloc(1, (upperLimit / 8) + sizeof(prime_t));
As it right now, you're allocating twice the bytes you need.
Also, if you want to defend against cases where there are more or less than 8 bits to a byte, use CHAR_BIT in the above code in place of 8. Whatever sizeof(uint64_t) evaluates to shouldn't matter, as you'll still get the proper number of bits required.
You allocate X bytes with calloc, dividing the total by sizeof(prime_t), yet act as if you have room for X prime_t elements later on.
Edit: Or actually even, you are allocating an array of 1 element with size X.
If you want to do it the way you are using it now, you should do:
calloc(X, sizeof(prime_t)) instead.
Edit: The major other issue in your code is that you are using byte-level indexing instead of bit-level.
Note that there are sizeof(prime_t) * 8 bits in a prime_t, so in every byte you set exactly 1 bit, true. You divide by sizeof(prime_t) instead of (sizeof(prime_t) * 8) when indexing.

Dec to bin converter function printing result out backwards

As part of an exercise, I have to rewrite a recursive function so that the new function is not recursive. Both functions need to convert positive decimal integer inputs into their binary equivalent.
This is the code using recursion:
void convert(int n) { //recursive
if (n > 0) {
convert(n/2);
printf("%d", n%2);
}
return;
}
Here's my code:
void convert(int n) { //non-recursive
while (n > 0) {
printf("%d", n%2);
n/=2;
}
return;
}
The problem with my code is that, understandably, my binary conversion gets printed out backwards. For example, if I enter the number 8, my function returns 0001, if I enter 2, 01 is returned, etc.
Any suggestions for a quick fix using only the stdio.h library?
Here's a non-recursive version that produces the same result as your recursive version and doesn't require an array:
void convert(int n) {
int s;
for (s = 1; n/s/2 > 0; s *= 2)
;
for (; s >= 1; s /= 2) {
printf("%d", (n/s) % 2);
}
}
This version handles zero and large numbers (but not negative numbers).
You can do this in one loop:
if(num == 0) {
printf("0\n"); // Check for num being 0.
return;
}
num = num < 0 ? num*-1 : num; // Make sure the number has no sign bit.
char first1Found = 0; // Create a check for the first 1 printed.
for (int i = sizeof(num)*8 - 1; i >= 0 ; --i) {
if (num & (1 << i)) { // If its a 1, print it and set the first1Found bool.
printf("1");
first1Found = 1;
} else if(first1Found) { // If its a 0 only print it if its not a leading 0.
printf("0");
}
}
printf("\n");
Here is a live example.
Note: I have used 8 by making an assumption that sizeof returns bytes in a type. This may not be true of all systems and compilers (although should be). A more portable way might be to use CHAR_BIT from <limits.h> as suggested by #chux.
Here's a variant that's explicit about using bit-masking and shifting the location of the mask from the upper end downwards. It behaves like your recursive version, in that it doesn't do negatives or zero.
void convert(int n) {
for(int mask = 1 << (8 * sizeof(n) - 2); mask > 0; mask >>= 1) {
if (mask <= n) {
putchar((n & mask) ? '1' : '0');
}
}
putchar('\n');
}
C99 variation on #Tom Karzes fine answer that handles all + and - values including INT_MIN.
void convertm(int n) {
if (n < 0) {
putchar('-');
} else {
n = -n;
}
// Build up a negative power-of-2 that meets/exceeds `n`
int npow2;
for (npow2 = -1; n/2 <= npow2 ; npow2 *= 2)
;
// For each negative power-of-2 ...
while (npow2) {
putchar(n / npow2 + '0');
n %= npow2;
npow2 /= 2;
}
puts("");
}
A reliable way to print an unpadded binary representation of an unsigned valued (any size capable of fitting within a long unsigned) is:
/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; };
size_t sz = sizeof v * CHAR_BIT;
unsigned long rem = 0;
while (sz--)
if ((rem = v >> sz))
putchar ((rem & 1) ? '1' : '0');
}
(CHAR_BIT (usually 8) is provided in limits.h). You do not "need" to use limits.h -- that's just where it CHAR_BIT is normally found. All you need is a constant, you can call it anything you like. I generally just use:
/* CHAR_BIT */
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

Calculate dynamic range of rand with mod

I want to create a rand() range between 1 and the dynamic value of bit_cnt.
After reading more about the rand() function, I understand that out of the box rand() has a range of [0, RAND_MAX]. I also understand that RAND_MAX's value is library-dependent, but is guaranteed to be at least 32767.
I had to create a bit mask of 64 0s.
Now, I am trying to left shift the bit mask by a dynamic value of bit_cnt anded with the a randomly generated number of bits between 1 and the dynamic value of bit_cnt.
For example, when bit_cnt is 10, I want to randomize the lowest 10 bits.
Originally, I had
mask = (mask << bit_cnt) + (rand()% bit_cnt);
which caused a floating point exception. From what I am understanding, that exception occurred because the value of bit_cntbecame 0.
Therefore, I attempted to create an if statement like this:
if((rand()%bit_cnt))!=0){
mask = (mask << bit_cnt) + (rand()% bit_cnt);
}
,but the floating point exception still occurred.
Then I tried the following thinking that the value not be 0 so increase the value to at least 1:
mask = (mask << bit_cnt) + ((rand()% bit_cnt)+1);
,but the floating point exception still occurred.
Afterwards, I tried the following:
mask = (mask << bit_cnt) + (1+(rand()%(bit_cnt+1)));
and the following 20 lines of 64 bits outputted:
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000000011
0000000000000000000000000000000000000000000000000000000000000101
0000000000000000000000000000000000000000000000000000000000001010
0000000000000000000000000000000000000000000000000000000000010011
0000000000000000000000000000000000000000000000000000000000100011
0000000000000000000000000000000000000000000000000000000001000110
0000000000000000000000000000000000000000000000000000000010000100
0000000000000000000000000000000000000000000000000000000100001001
0000000000000000000000000000000000000000000000000000001000000010
0000000000000000000000000000000000000000000000000000010000000100
0000000000000000000000000000000000000000000000000000100000000111
0000000000000000000000000000000000000000000000000001000000000101
0000000000000000000000000000000000000000000000000010000000001001
0000000000000000000000000000000000000000000000000100000000000111
0000000000000000000000000000000000000000000000001000000000001111
0000000000000000000000000000000000000000000000010000000000001010
0000000000000000000000000000000000000000000000100000000000000101
0000000000000000000000000000000000000000000001000000000000001101
0000000000000000000000000000000000000000000010000000000000001100
What was the cause of the floating point exception? Is this how to dynamic create a range of the rand() function?
I appreciate any suggestions. Thank you.
UPDATE:
I changed the if statement to be the following:
if(bit_cnt !=0)
and then performed the rest of the logic.
I received the following output:
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000000100
0000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000010010
0000000000000000000000000000000000000000000000000000000000100001
0000000000000000000000000000000000000000000000000000000001000100
0000000000000000000000000000000000000000000000000000000010000110
0000000000000000000000000000000000000000000000000000000100000011
0000000000000000000000000000000000000000000000000000001000000000
0000000000000000000000000000000000000000000000000000010000001000
0000000000000000000000000000000000000000000000000000100000000111
0000000000000000000000000000000000000000000000000001000000000110
0000000000000000000000000000000000000000000000000010000000000110
0000000000000000000000000000000000000000000000000100000000001100
0000000000000000000000000000000000000000000000001000000000000010
0000000000000000000000000000000000000000000000010000000000001101
0000000000000000000000000000000000000000000000100000000000000110
0000000000000000000000000000000000000000000001000000000000010000
0000000000000000000000000000000000000000000010000000000000000100
Is there any possible way to know if the range is correct? Like is there any possible way to know by looking at the output?
const int LINE_CNT = 20;
void print_bin(uint64_t num, unsigned int bit_cnt);
uint64_t rand_bits(unsigned int bit_cnt);
int main(int argc, char *argv[]) {
int i;
srand(time(NULL));
for(i = 0; i < LINE_CNT; i++) {
uint64_t val64 = rand_bits(i);
print_bin(val64, 64);
}
return EXIT_SUCCESS;
}
void print_bin(uint64_t num, unsigned int bit_cnt) {
int top_bit_cnt;
if(bit_cnt <= 0) return;
if(bit_cnt > 64) bit_cnt = 64;
top_bit_cnt = 64;
while(top_bit_cnt > bit_cnt) {
top_bit_cnt--;
printf(" ");
}
while(bit_cnt > 0) {
bit_cnt--;
printf("%d", (num & ((uint64_t)1 << bit_cnt)) != 0);
}
printf("\n");
return;
}
uint64_t rand_bits(unsigned int bit_cnt) {
uintmax_t mask = 1;
if (bit_cnt != 0) {
mask = (mask << bit_cnt) + (rand()% bit_cnt);
}
return mask;
}
I am trying to modify the function rand_bits to return all 0 expect for the lowest bits aka bit_cnt which are randomized.
Returns a 64 bit pattern with all zeros except for the lowest requested bits, which are randomized. This allows for arbitrary length random bit patterns in a portable fashion as the C standard "rand()" function is only required to return
random numbers between 0 and 32767... effectively, a random 15 bit pattern.
Parameter, "bit_cnt": How many of the lowest bits, including the lowest order bit (bit 0) to be randomized.
UPDATE: Added Barmar's newest suggestion of mask = rand() % (1 << bit_cnt);:
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000001001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000000010101
0000000000000000000000000000000000000000000000000000000001001111
0000000000000000000000000000000000000000000000000000000010000011
0000000000000000000000000000000000000000000000000000001010101001
0000000000000000000000000000000000000000000000000000010101101100
0000000000000000000000000000000000000000000000000000101011111000
0000000000000000000000000000000000000000000000000001001010101111
0000000000000000000000000000000000000000000000000011101011000101
0000000000000000000000000000000000000000000000000001001101111101
0000000000000000000000000000000000000000000000001111000000111010
0000000000000000000000000000000000000000000000000101100000001100
0000000000000000000000000000000000000000000000100111101000111111
0000000000000000000000000000000000000000000001010101011101000110
uint64_t rand_bits(unsigned int bit_cnt) {
uintmax_t mask = 1;
if (bit_cnt != 0) {
mask = rand() % (1 << bit_cnt);
}
return mask;
}
The problem is that anything % bit_cnt will get an error if bit_cnt is 0. You need to check bit_cnt before you try to perform the modulus.
if (bit_cnt != 0) {
mask = (mask << bit_cnt) + (rand()% bit_cnt) + 1;
}
All your attempts performed the modulus and then tried to do something with the result, but that's after the error happens.
This uses the bit count to generate a mask. If you want a bit count greater than can be filled by RAND_MAX, implement another random function as I commented earlier.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int bit_cnt = 10;
unsigned mask = 0;
int i;
int num;
srand((unsigned)time(NULL));
for(i = 0; i < bit_cnt; i++)
mask = (mask << 1) | 1;
printf ("For bit_cnt=%d, mask=0x%X\n\n", bit_cnt, mask);
for (i = 0; i < 5; i++) {
num = rand() & mask;
printf("Random number 0x%0*X\n", 1+(bit_cnt-1)/4, num);
}
}
Program output:
For bit_cnt=10, mask=0x3FF
Random number 0x327
Random number 0x39C
Random number 0x1B1
Random number 0x088
Random number 0x26E

Is this the proper way to count the number of 0s in a binary number?

#include <stdio.h>
int NumberOfSetBits(int);
int main(int argc, char *argv[]) {
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
int n = 3;
int count = NumberOfSetBits(n);
printf("Number of set bits is: %d\n", count);
printf("Number of unset bits is: %d", total_bit_size - count);
}
int NumberOfSetBits(int x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x = x >> 1;
}
return count;
}
Number of set bits is: 2
Number of unset bits is: 30
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
^ that will get the size of the int on the system and times it by 8 which is the number of bits in each byte
EDITED: Without the use of the ~
/*
Calculate how many set bits and unset bits are in a binary number aka how many 1s and 0s in a binary number
*/
#include <stdio.h>
unsigned int NumberOfSetBits(unsigned int);
unsigned int NumberOfUnSetBits(unsigned int x);
int main() {
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
unsigned int n = 3;
printf("Number of set bits is: %u\n", NumberOfSetBits(n));
printf("Number of unset bits is: %u", NumberOfUnSetBits(n));
return 0;
}
unsigned int NumberOfSetBits(unsigned int x) {
// counts the number of 1s
unsigned int count = 0;
while (x != 0) {
count += (x & 1);
// moves to the next bit
x = x >> 1;
}
return count;
}
unsigned int NumberOfUnSetBits(unsigned int x) {
// counts the number of 0s
unsigned int count = 0;
while(x != 0) {
if ((x & 1) == 0) {
count++;
}
// moves to the next bit
x = x >> 1;
}
return count;
}
returns for input 3
Number of set bits is: 2
Number of unset bits is: 0
unset bits is 0? Doesn't seem right?
if I use NumberOfSetBits(~n) it returns 30
You've got a problem on some systems because you right shift a signed integer in your bit-counting function, which may shift 1's into the MSB each time for negative integers.
Use unsigned int (or just unsigned) instead:
int NumberOfSetBits(unsigned x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x >>= 1;
}
return count;
}
If you fix that part of the problem, you can solve the other with:
int nbits = NumberOfSetBits(~n);
where ~ bitwise inverts the value in n, and hence the 'set bit count' counts the bits that were zeros.
There are also faster algorithms for counting the number of bits set: see Bit Twiddling Hacks.
To solve the NumberOfSetBits(int x) version without assuming 2's complement nor absence of padding bits is a challenge.
#Jonathan Leffler has the right approach: use unsigned. - Just thought I'd try a generic int one.
The x > 0, OP's code work fine
int NumberOfSetBits_Positive(int x) {
int count = 0;
while (x != 0) {
count += (x & 1);
x = x >> 1;
}
return count;
}
Use the following to find the bit width and not count padding bits.
BitWidth = NumberOfSetBits_Positive(INT_MAX) + 1;
With this, the count of 0 or 1 bits is trivial.
int NumberOfClearBits(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits(x);
}
int NumberOfSetBits_Negative(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
All that is left is to find the number of bits set when x is 0. +0 is easy, the answer is 0, but -0 (1's compliment or sign magnitude) is BitWidth or 1.
int NumberOfSetBits(int x) {
if (x > 0) return NumberOfSetBits_Positive(x);
if (x < 0) return NumberOfSetBits_Negative(x);
// Code's assumption: Only 1 or 2 forms of 0.
/// There may be more because of padding.
int zero = 0;
// is x has same bit pattern as +0
if (memcmp(&x, &zero, sizeof x) == 0) return 0;
// Assume -0
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
here is a proper way to count the number of zeores in a binary number
#include <stdio.h>
unsigned int binaryCount(unsigned int x)
{
unsigned int nb=0; // will count the number of zeores
if(x==0) //for the case zero we need to return 1
return 1;
while(x!=0)
{
if ((x & 1) == 0) // the condition for getting the most right bit in the number
{
nb++;
}
x=x>>1; // move to the next bit
}
return nb;
}
int main(int argc, char *argv[])
{
int x;
printf("input the number x:");
scanf("%d",&x);
printf("the number of 0 in the binary number of %d is %u \n",x,binaryCount(x));
return 0;
}

Resources