A pseudo-random number generator based on 2 inputs [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I need to generate a pseudo-random number based on 2 input values X and Y. Given the same X and Y values I need to get the same result. The result should be between 0 and 1 inclusive.
So far I have this:
const int a = 0x7fffffff / 48271;
const int b = 0x7fffffff % 48397;
float rand(int x, int y) {
float seed, result;
seed = x ^ ((y << 1) & 0x2AAAAAAA) ^ ((y >> 1) & 0x33333333);
result = 48353 * (seed % a) - b * (seed / a);
return (result);
}
It's giving me a result but not what I'm looking for. I've cobbled it together from random things I've seen on the net, so no idea if it's really any good.

Borrowing from xxHash:
float rand(uint32_t x, uint32_t y) {
/* mix around the bits in x: */
x = x * 3266489917 + 374761393;
x = (x << 17) | (x >> 15);
/* mix around the bits in y and mix those into x: */
x += y * 3266489917;
/* Give x a good stir: */
x *= 668265263;
x ^= x >> 15;
x *= 2246822519;
x ^= x >> 13;
x *= 3266489917;
x ^= x >> 16;
/* trim the result and scale it to a float in [0,1): */
return (x & 0x00ffffff) * (1.0f / 0x1000000);
}
The general idea is to subject x and y to a variety of 1:1 transforms and to mix those together to distribute all of the input bits evenly(ish) throughout the result. Then the result in floating-point to [0,1). I've excluded 1.0 from the possible outputs because including it turns out to be kind of fiddly.
Multiplication by any odd number, with unsigned overflow, is a 1:1 transform because odd numbers are all co-prime with powers of two (the range limit of a uint32_t). Unfortunately multiplication only allows low order bits to affect high order bits; it doesn't allow high bits to affect low. To make up for that, we have a few x ^= x >> k terms, to mix high bits into low positions.

To "get the same result" the PRNG state needs to be at least as many bits as the sum of x,y bit-width. float is not wide enough.
By "same result", I assume that means the same sequence of numbers generated.
long double might work for you, but it appears you need a new PRNG algorithm with a much wider state.

Related

Converting float negative values to integer value in c launguage [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to convert float negative values to unsigned int values. Is it possible?
For example:
float x = -10000.0;
int y;
y = x;
When we assign x value to y, can the negative value be stored in an integer?
If not, how can we store the negative values into integer variables?
can the negative (float f) value be stored in an integer?
Yes, with limitations.
With a signed integer type like int16_t i, i = f is well defined for
-32768.999... to 32767.999...
With an unsigned integer type like unt16_t u, u = f is well defined for
-0.999... to 65535.999...
The result is a truncated value (fraction thrown away). All other float values result in undefined behavior.
If not, how can we store the negative values into integer variables?
Best to use wide signed integer types and test for range limitations.
In any case, the fraction of the float is lost. A -0.5f can be stored in an unsigned, yet the value becomes 0u.
The below performs some simply tests to insure y is in range.
#include <limits.h>
float x = ...;
int y = 0;
if (x >= INT_MAX + 1u) puts("Too pos");
else if (x <= INT_MIN - 1.0) puts("Too neg");
else y = (int) x;
Note the tests above are illustrative as they lack high portability.
Example: INT_MIN - 1.0 in inexact in select situations.
To cope, with common 2's complement int, the below is better reformed. As 2's complement, INT_MIN is a power of 2 (negated) and usually in the range of float, thus making for an exact subtraction near the negative threshold. `
// if (x <= INT_MIN - 1.0)
if (x - INT_MIN <= - 1.0f)
Another alternative is to explore a union. Leave that for others to explain its possibilities and limitations.
union {
float f;
unsigned u;
} x;
float x = 10000.0;
int a;
a = (int)(x+0.5);

C program to get average of 2 numbers in a 16 bit processor

How do we write a program in C which can calculate an average of 2 16 bit signed numbers on a 16 bit processor.
int getAverage(int x, int y)
{
int result=0;
result = ((x+y)/2);
return result;
}
The above works for most cases except for when both x and y are max values 65535.
In the case where both x and y are positive or negative numbers, I would divide the difference between the numbers by 2 and add that result to the number that is subtracted. Mathematically, this is equivalent to what you currently have:
(y - x)/2 + x = y/2 - x/2 + x = y/2 + x/2 = (x + y)/2
If x is positive and y is negative or vice versa, the original method of calculation that you have should be used.
Simplest possible solution with some crude integer rounding:
int32_t getAverage (int16_t x, int16_t y)
{
int32_t sum = (int32_t)x + (int32_t)y;
return sum/2 + sum%2;
}
This will work just fine since your 16 bit compiler will have software routines to handle 32 bit integers.

c change the exponent of a double

Lets say I have a double a = 0.3;. How would I be able to change the exponent of the variable, without using math functions like pow(), or multiplying it manually.
I am guessing I would have to acces the memory addres of the variable using pointers, find the exponent and change it manualy. But how would I accomplish this?
Note, that this is on a 8-bit system, and I am trying to find a faster way to multiply the number by 10^12, 10^9, 10^6 or 10^3.
Best regards!
Note that a*10^3 = a*1000 = a*1024 - a*16 - a*8 = a*2^10 - a*2^4 - a*2^3.
So you can calculate a*10^3 as follows:
Read the 11 exponent bits into int exp
Read the 52 fraction bits into double frac
Calculate double x with exp+10 as the exponent and frac as the fraction
Calculate double y with exp+4 as the exponent and frac as the fraction
Calculate double z with exp+3 as the exponent and frac as the fraction
Calculate the output as x-y-z, and don't forget to add the sign bit if a < 0
You can use a similar method for the other options (a*10^6, a*10^9 and a*10^12)...
Here is how you can do the whole thing in a "clean" manner:
double MulBy1000(double a)
{
double x = a;
double y = a;
double z = a;
unsigned long long* px = (unsigned long long*)&x;
unsigned long long* py = (unsigned long long*)&y;
unsigned long long* pz = (unsigned long long*)&z;
*px += 10ULL << 52;
*py += 4ULL << 52;
*pz += 3ULL << 52;
return x - y - z;
}
Please note that I'm not sure whether or not this code breaks strict-aliasing rules.
Multiplying a number by 10 is the equivalent of
a) Multiplying the original number by 2
b) Multiplying the original number by 8
c) Adding the results of (a) and (b).
This works because to is binary 1010.
One approach would therefore be to increment the exponent (for (a)), add 3 to the exponent (for (b)), then add the results.
To multiply by 10^n, repeat the above n times. Alternatively work out the binary representation of 1,000, 1,000,000, etc, and add the relevant 1s. You may make things easier by noting that 1000 for instance 1024 (for instance) is 1024 - 16 - 8, i.e.
a) Add 10 to the exponent of the original to multiply by 1024
b) Add 4 to the exponent of the original to multiply by 16
c) Add 3 to the exponent of the original to multiply by 8
d) From (a) subtract (b) and (c) to get the answer.
Again, you can do that multiple times for 10^6, 10^9 etc.
For a quick approximation and powers of n which are multiples of 3, just add 10n/3 to the exponent (as 1024 ~= 1000)
For fun a simple recursive solution.
double ScalePower10(double x, unsigned power) {
if (power <= 1) {
if (power == 0) return x;
return x * 10.0;
}
double y = ScalePower10(x, power/2);
y = y*y;
if (power%2) y *= 10.0;
return y;
}

bitwise division by multiples of 2

I found many posts about bitwise division and I completely understand most bitwise usage but I can't think of a specific division. I want to divide a given number (lets say 100) with all the multiples of 2 possible (ATTENTION: I don't want to divide with powers of 2 bit multiples!)
For example: 100/2, 100/4, 100/6, 100/8, 100/10...100/100
Also I know that because of using unsigned int the answers will be rounded for example 100/52=0 but it doesn't really matter, because I can both skip those answers or print them, no problem. My concern is mostly how I can divide with 6 or 10, etc. (multiples of 2). There is need for it to be done in C, because I can manage to transform any code you give me from Java to C.
Following the math shown for the accepted solution to the division by 3 question, you can derive a recurrence for the division algorithm:
To compute (int)(X / Y)
Let k be such that 2k &geq; Y and 2k-1 < Y
(note, 2k = (1 << k))
Let d = 2k - Y
Then, if A = (int)(X / 2k) and B = X % 2k,
X = (1 << k) * A + B
= (1 << k) * A - Y * A + Y * A + B
= d * A + Y * A + B
= Y * A + (d * A + B)
Thus,
X/Y = A + (d * A + B)/Y
In otherwords,
If S(X, Y) := X/Y, then S(X, Y) := A + S(d * A + B, Y).
This recurrence can be implemented with a simple loop. The stopping condition for the loop is when the numerator falls below 2k. The function divu implements the recurrence, using only bitwise operators and using unsigned types. Helper functions for the math operations are left unimplemented, but shouldn't be too hard (the linked answer provides a full add implementation already). The rs() function is for "right-shift", which does sign extension on the unsigned input. The function div is the actual API for int, and checks for divide by zero and negative y before delegating to divu. negate does 2's complement negation.
static unsigned divu (unsigned x, unsigned y) {
unsigned k = 0;
unsigned pow2 = 0;
unsigned mask = 0;
unsigned diff = 0;
unsigned sum = 0;
while ((1 << k) < y) k = add(k, 1);
pow2 = (1 << k);
mask = sub(pow2, 1);
diff = sub(pow2, y);
while (x >= pow2) {
sum = add(sum, rs(x, k));
x = add(mul(diff, rs(x, k)), (x & mask));
}
if (x >= y) sum = add(sum, 1);
return sum;
}
int div (int x, int y) {
assert(y);
if (y > 0) return divu(x, y);
return negate(divu(x, negate(y)));
}
This implementation depends on signed int using 2's complement. For maximal portability, div should convert negative arguments to 2's complement before calling divu. Then, it should convert the result from divu back from 2's complement to the native signed representation.
The following code works for positive numbers. When the dividend or the divisor or both are negative, have flags to change the sign of the answer appropriately.
int divi(long long m, long long n)
{
if(m==0 || n==0 || m<n)
return 0;
long long a,b;
int f=0;
a=n;b=1;
while(a<=m)
{
b = b<<1;
a = a<<1;
f=1;
}
if(f)
{
b = b>>1;
a = a>>1;
}
b = b + divi(m-a,n);
return b;
}
Use the operator / for integer division as much as you can.
For instance, when you want to divide 100 by 6 or 10 you should write 100/6 or 100/10.
When you mention bit wise division do you (1) mean an implementation of operator / or (2) you are referring to the division by a power of two number.
For (1) a processor should have an integer division unit. If not the compiler should provide a good implementation.
For (2) you can use 100>>2 instead of 100/4. If the numerator is known at compile time then a good compiler should automatically use the shift instruction.

Bitwise overflow checking in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to write two functions that will check/prevent overflow in c (using only ! ~ | & ^ +) but cant get it. The first is will a certain twos compliment/signed int will fit in a certatin amount of bits: fitsB(int x, int n) where is the int and n is the size of bits to use. Also a function that will check to see if two ints will not overflow when added together: overflowInt(int x, int y). I can get it if they are unsigned ints but the negatives just make things harder for me. Anyone know how to?
There also is no casting and ints are always 32 bit
/*
* addOK - Determine if can compute x+y without overflow
* Example: addOK(0x80000000,0x80000000) = 0,
* addOK(0x80000000,0x70000000) = 1,
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int addOK(int x, int y) {
// Find the sign bit in each word
//if a and b have different signs, you cannot get overflow.
//if they are the same, check that a is different from c and b is different from c,
// if they are the same, then there was no overflow.
int z=x+y;
int a=x>>31;
int b=y>>31;
int c=z>>31;
return !!(a^b)|(!(a^c)&!(b^c));
}
x will fit in n bits if x < 2^(n-1).
The overflow question needs more information. Two ints will not overflow if you assign them to a long (or a double).
Using the above example (Adam Shiemke), you can find the maximum (positive) value and minimum value (negative) to get the range for n number of bits. 2^(n-1) (from Adam's example) and minus one for the maximum/positive number which can be represented in the n bits. For the minimum value, negate 2^(n-1) to get the minimum value x => -(2^(n-1)); (Note the >= not > for the minimum range). For example, for n = 4 bits, 2^(4-1) - 1 = 2^3 -1 = 7 so x <= 7 and x >= -8 = (-(2^(4-1)).
This assumes the initial input does not overflow a 32 bit quanity (Hopefully an error occurs in that condition) and the number of bits you are using is less then 32 (as you are adding 1 for the negative range and if you have 32 bits, it will overflow, see below for an explanation).
To determine if addition will overflow, if you have the maximum value, the x + y <= maximum value. By using algebra, we can get y <= maximum value - x. You can then compare the passed in value for y and if it does not meet the condition, the addition will overflow. For example if x is the maximumn value, then y <= 0, so y must be less then or equal to zero or the addition will overflow.

Resources