Getting a random number without the Random library [closed] - java

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I would like to get random numbers between a range I give, but the problem I don't want to use the Random library of Java or anything I have to initializate.
Does anyone know an alternative way to get random numbers without using the java library?
Thanks
EDIT: What do you think about this solution?
int random = i + (int)(System.currentTimeMillis()%((j - i) + 1));
Where i and j are the range

You have to implement your own pseudo-random number generation algorithm, which is literally reinventing the wheel and will not be secure!
Another solution is to use a service that generates true random numbers like Random.org

I learned that the best method for generating the most random numbers is using the Mersenne Twister random number generator. This generator will provide you with enough random numbers to not need to reseed, it has a period of (2^19937) − 1
Here is source code for MerseeneTwister
https://java2s.com/Open-Source/Java/Natural-Language-Processing/MorphAdorner/edu/northwestern/at/utils/math/randomnumbers/MersenneTwister.java.htm
Here is a class to generate your random numbers.
class RandomVariable {
/** Initialize Mersenne Twister generator. */
private static MersenneTwister rnd = new MersenneTwister();
public static double rand() {
return rnd.nextDouble();
}
/** Generate a random number from a uniform random variable.
*
* #param min Mininum value for the random variable.
* #param max Maximum value for the random variable.
*
* #return A random double between min and max.
*/
public static double uniform(double min, double max) {
return min + (max - min) * rand();
}
}
Here is a sample to generate a random number. Please note that I removed the comments from the source. This may voliate the open source nature of the code, but I couldnt copy it all and have it formated as code.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class sample{
public static void main(String args[]){
RandomVariable gen = new RandomVariable();
double num = gen.uniform(-1,1);
int n = 10000;
Set<Double> nums = new HashSet<Double>();
while (numbers.size() < n)
nums.add(gen.uniform(-1,1));
}
}
class RandomVariable {
/** Initialize Mersenne Twister generator. */
private static MersenneTwister rnd = new MersenneTwister();
public static double rand() {
return rnd.nextDouble();
}
/** Generate a random number from a uniform random variable.
*
* #param min Mininum value for the random variable.
* #param max Maximum value for the random variable.
*
* #return A random double between min and max.
*/
public static double uniform(double min, double max) {
return min + (max - min) * rand();
}
}
class MersenneTwister extends java.util.Random implements Serializable {
// Period parameters
private static final int N = 624;
private static final int M = 397;
private static final int MATRIX_A = 0x9908b0df; // private static final
//* constant vector a
private static final int UPPER_MASK = 0x80000000; // most significant
// w-r bits
private static final int LOWER_MASK = 0x7fffffff; // least significant
// r bits
// Tempering parameters
private static final int TEMPERING_MASK_B = 0x9d2c5680;
private static final int TEMPERING_MASK_C = 0xefc60000;
private int mt[]; // the array for the state vector
private int mti; // mti==N+1 means mt[N] is not initialized
private int mag01[];
// a good initial seed (of int size, though stored in a long)
// private static final long GOOD_SEED = 4357;
/* implemented here because there's a bug in Random's implementation
of the Gaussian code (divide by zero, and log(0), ugh!), yet its
gaussian variables are private so we can't access them here. :-( */
private double __nextNextGaussian;
private boolean __haveNextNextGaussian;
/**
* Constructor using the default seed.
*/
public MersenneTwister() {
this(System.currentTimeMillis());
}
/**
* Constructor using a given seed. Though you pass this seed in
* as a long, it's best to make sure it's actually an integer.
*/
public MersenneTwister(final long seed) {
super(seed); /* just in case */
setSeed(seed);
}
/**
* Constructor using an array.
*/
public MersenneTwister(final int[] array) {
super(System.currentTimeMillis());
/* pick something at random just in case */
setSeed(array);
}
/**
* Initalize the pseudo random number generator. Don't
* pass in a long that's bigger than an int (Mersenne Twister
* only uses the first 32 bits for its seed).
*/
synchronized public void setSeed(final long seed) {
// it's always good style to call super
super.setSeed(seed);
// Due to a bug in java.util.Random clear up to 1.2, we're
// doing our own Gaussian variable.
__haveNextNextGaussian = false;
mt = new int[N];
mag01 = new int[2];
mag01[0] = 0x0;
mag01[1] = MATRIX_A;
mt[0] = (int) (seed & 0xfffffff);
for (mti = 1; mti < N; mti++) {
mt[mti] =
(1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >>> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffff;
/* for >32 bit machines */
}
}
/**
* An alternative, more complete, method of seeding the
* pseudo random number generator. array must be an
* array of 624 ints, and they can be any value as long as
* they're not *all* zero.
*/
synchronized public void setSeed(final int[] array) {
int i, j, k;
setSeed(19650218);
i = 1;
j = 0;
k = (N > array.length ? N : array.length);
for (; k != 0; k--) {
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1664525))
+ array[j] + j; /* non linear */
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
i++;
j++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
if (j >= array.length) {
j = 0;
}
}
for (k = N - 1; k != 0; k--) {
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1566083941))
- i; /* non linear */
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
i++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
}
mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
}
/**
* Returns an integer with <em>bits</em> bits filled with a random number.
*/
synchronized protected int next(final int bits) {
int y;
if (mti >= N) // generate N words at one time
{
int kk;
final int[] mt = this.mt; // locals are slightly faster
final int[] mag01 = this.mag01; // locals are slightly faster
for (kk = 0; kk < N - M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < N - 1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++];
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
return y >>> (32 - bits); // hope that's right!
}
/* If you've got a truly old version of Java, you can omit these
two next methods. */
private synchronized void writeObject(final ObjectOutputStream out)
throws IOException {
// just so we're synchronized.
out.defaultWriteObject();
}
private synchronized void readObject(final ObjectInputStream in)
throws IOException, ClassNotFoundException {
// just so we're synchronized.
in.defaultReadObject();
}
/** This method is missing from jdk 1.0.x and below. JDK 1.1
includes this for us, but what the heck.*/
public boolean nextBoolean() {
return next(1) != 0;
}
/** This generates a coin flip with a probability <tt>probability</tt>
of returning true, else returning false. <tt>probability</tt> must
be between 0.0 and 1.0, inclusive. Not as precise a random real
event as nextBoolean(double), but twice as fast. To explicitly
use this, remember you may need to cast to float first. */
public boolean nextBoolean(final float probability) {
if (probability < 0.0f || probability > 1.0f) {
throw new IllegalArgumentException("probability must be between 0.0"
+ " and 1.0 inclusive.");
}
if (probability == 0.0f) {
return false; // fix half-open issues
} else if (probability == 1.0f) {
return true; // fix half-open issues
}
return nextFloat() < probability;
}
/** This generates a coin flip with a probability <tt>probability</tt>
of returning true, else returning false. <tt>probability</tt> must
be between 0.0 and 1.0, inclusive. */
public boolean nextBoolean(final double probability) {
if (probability < 0.0 || probability > 1.0) {
throw new IllegalArgumentException("probability must be between 0.0"
+ " and 1.0 inclusive.");
}
if (probability == 0.0) {
return false; // fix half-open issues
} else if (probability == 1.0) {
return true; // fix half-open issues
}
return nextDouble() < probability;
}
/** This method is missing from JDK 1.1 and below. JDK 1.2
includes this for us, but what the heck. */
public int nextInt(final int n) {
if (n <= 0) {
throw new IllegalArgumentException("n must be >= 0");
}
if ((n & -n) == n) {
return (int) ((n * (long) next(31)) >> 31);
}
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
/** This method is for completness' sake.
Returns a long drawn uniformly from 0 to n-1. Suffice it to say,
n must be > 0, or an IllegalArgumentException is raised. */
public long nextLong(final long n) {
if (n <= 0) {
throw new IllegalArgumentException("n must be >= 0");
}
long bits, val;
do {
bits = (nextLong() >>> 1);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
/** A bug fix for versions of JDK 1.1 and below. JDK 1.2 fixes
this for us, but what the heck. */
public double nextDouble() {
return (((long) next(26) << 27) + next(27))
/ (double) (1L << 53);
}
/** A bug fix for versions of JDK 1.1 and below. JDK 1.2 fixes
this for us, but what the heck. */
public float nextFloat() {
return next(24) / ((float) (1 << 24));
}
/** A bug fix for all versions of the JDK. The JDK appears to
use all four bytes in an integer as independent byte values!
Totally wrong. I've submitted a bug report. */
public void nextBytes(final byte[] bytes) {
for (int x = 0; x < bytes.length; x++) {
bytes[x] = (byte) next(8);
}
}
/** For completeness' sake, though it's not in java.util.Random. */
public char nextChar() {
// chars are 16-bit UniCode values
return (char) (next(16));
}
/** For completeness' sake, though it's not in java.util.Random. */
public short nextShort() {
return (short) (next(16));
}
/** For completeness' sake, though it's not in java.util.Random. */
public byte nextByte() {
return (byte) (next(8));
}
/** A bug fix for all JDK code including 1.2. nextGaussian can theoretical
* ly
ask for the log of 0 and divide it by 0! See Java bug
<a href="http://developer.java.sun.com/developer/bugParade/bugs/4254501.h
* tml">
http://developer.java.sun.com/developer/bugParade/bugs/4254501.html</a>
*/
synchronized public double nextGaussian() {
if (__haveNextNextGaussian) {
__haveNextNextGaussian = false;
return __nextNextGaussian;
} else {
double v1, v2, s;
do {
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = /* Strict*/ Math.sqrt(-2
* /* Strict*/ Math.log(s) / s);
__nextNextGaussian = v2 * multiplier;
__haveNextNextGaussian = true;
return v1 * multiplier;
}
}
}

There is a default random method in java.lang.math.
It returns a double between 0.0 and 1.0 (0.0 <= n < 1.0).
You can do some simple tricks to convert this to various random values:
boolean coinFlip = (Math.random() >= 0.5);
int card = (int)(Math.random() * 52);
However, this makes a new java.util.Random() behind the scenes, which I think you are trying to avoid.
If you don't want to use any library, then you have to make your own implementation, which will probably end up being much more complicated.
You mentioned using time, this could certainly work for generating numbers, but for any practical purpose it is not really random. Something like:
long betweenOneAndTen = 1 + (System.currentTimeMillis() % 10);

If you use the Math.random() function, you are neiter making a dependence on the Random class nor initializing anything (at least it's not your responsibility). There is no fundamental difference between calling System.currentTimeMillis(), System.nanoTime() and Math.random()---except that the latter is more performant and better at returning a random value.

Related

Problems with formula to output a triangle waveform in Java

I got my wave file creator working and I split it into three classes, I also made a sinewave generator that inherits from an abstract class called waveform and I can export 8 and 16 bit mono or sterio sine waves. I am trying to make a class called TriangleWave Generator to output a triangle wave tone, but I can't get the algebra from https://en.wikipedia.org/wiki/Triangle_wave#, the first formula, to work. It will only export the highest harmonic stated and not blend them together with the fundamental
Sample length: length in seconds
point: individual sample
amp limit: the highest position possible
harmonics: the number of harmonics to use to make the waveform 1 = fundamental, 2 = 1st overtone, 3 = 2nd overtone.......
frequency: fundamental frequency (Middle C = 261.63)
sample rate = 44100; (CD quality)
triangle Samples array: sample data
This is my code
public class TriangleGenerator extends Waveform {
// constants
public static final int HARMONIC_COUNT = 16;
// instance variabls
int harmonics;
int[] triangleSample;
int addCount;
// constructor
public TriangleGenerator(double amplitude, double frequency, int bitRate, double duration, int harmonics) {
super(amplitude, frequency, bitRate, duration);
// sample data
triangleSample = new int[sampleLength];
calculateAmpLimit();
this.harmonics = harmonics;
}
// one arg cunstructor
public TriangleGenerator(double frequency) {
this(AMPLITUDE, frequency, BIT_RATE, DURATION, HARMONIC_COUNT);
}
// no args constructor
public TriangleGenerator() {
this(AMPLITUDE, FREQUENCY, BIT_RATE, DURATION, HARMONIC_COUNT);
}
#Override
public int[] generateWaveForm() {
// generate the actual waveform
for (int i = 0; i < sampleLength; i++) {
point = (int)(ampLimit * ((8 / Math.pow(Math.PI, 2)) * sumnate(harmonics - 1, Math.pow(-1, addCount))
* Math.pow(harmonics, -2) * Math.sin(2 * Math.PI * frequency * harmonics * i / SAMPLE_RATE)));
triangleSample[i] = point;
}
// return the sample data
return triangleSample;
}
public double sumnate(int n, double adder) {
double sum = 0;
for (addCount = 0; addCount <= n; addCount++) {
sum += adder;
}
return sum;
}
}
In the formula for the triangle wave:
the mode number n is dependent on the harmonic label i:
This means that it must also be summed over the components
which doesn't happen in the current implementation. One possible implementation is:
public int[] generateWaveForm() {
for (int t = 0; t < sampleLength; t++) {
triangleSample[t] = (int)(ampLimit * 8.0 / Math.pow(Math.PI, 2.0) * getDataPoint(t, N));
}
return triangleSample;
}
private double getDataPoint(int t, int N) {
double sum = 0;
for (int i = 0; i <= N - 1; i++) {
sum += getHarmonicShare(t, i);
}
return sum;
}
private double getHarmonicShare(int t, int i) {
double n = 2.0 * i + 1.0;
return Math.pow(-1.0, i) * Math.pow(n, -2.0) * Math.sin(2.0 * Math.PI * frequency * (t / SAMPLE_RATE) * n);
}
Here t, i, n and N correspond to the values from the formula. frequency denotes the frequency. The remaining values correspond to the parameters of the posted code.
The curve reaches up to the value sampleLength / SAMPLE_RATE. The period is 1 / frequency and there are (sampleLength / SAMPLE_RATE) * frequency periods in the displayed frame.
Example:
sampleLength: 500
ampLimit: 100.00
SAMPLE_RATE: 44100.00
frequency: 261.63
sampleLength / SAMPLE_RATE: 0.0113378685
1 / frequency: 0.0038221916
(sampleLength / SAMPLE_RATE) * frequency: 2.9663265306
In the following the corresponding curve is shown for different N using JFreeChart:
Is there a reason you want to use sin to do this rather than produce the straight lines directly by a linear formula? There is an advantage in using sin in that you don't get harmonic distortion from aliasing, but if that's an issue then you can oversample. The issue is that sin is much slower than basic arithmetic.

Random strings with given length unit testing

I have a program that is generating pseudo random numbers(Only lowercase, uppercase and digits are allowed).
/**
*
* #return - returns a random digit (from 0 to 9)
*
*/
int randomDigits() {
return (int) (Math.random() * 10);
}
/**
*
* #return - returns a random lowercase (from "a" to "z")
*/
char randomLowerCase() {
return (char) ('a' + Math.random() * 26);
}
/**
*
* #return - returns a random uppercase (from "A" to "Z")
*/
char randomUpperCase() {
return (char) ('A' + Math.random() * 26);
}
/**
*
* #return - returns a random number between 1 and 3.
*
*/
char randomChoice() {
return (char) ((char) (Math.random() * 3) + 1);
}
/**
*
* #param length
* - the length of the random string.
* #return - returns a combined random string. All elements are builder side
* by side.
*
* We use the randomChoice method to get randomly upper, lower and
* digits.
*/
public String stringBuilder(int length) {
StringBuilder result = new StringBuilder();
int len = length;
for (int i = 0; i < len; i++) {
int ch = randomChoice();
if (ch == 1) {
result.append(randomDigits());
}
if (ch == 2) {
result.append(randomLowerCase());
}
if (ch == 3) {
result.append(randomUpperCase());
}
}
return result.toString();
}
How can i make a test for that code. I try to test the range for the digits (form 0 to 9)
int minRange = 0;
int maxRange = 0;
for (int i = 0; i < 100000; i++) {
int result = item.randomDigits();
if (result == 52) {
minRange++;
} else {
if (result == 19) {
maxRange++;
}
}
}
LOGGER.info("The min range in the digit is 0, and in the test appeared: {}", minRange);
LOGGER.info("The max range in the digit is 9, and in the test appeared: {}", maxRange);
But i cant find how to test the lower or upper?
Testing code which uses any randomness is tricky. There are two approaches you can take:
Your test can have sufficient iterations that it has a good chance to show any errors in your logic. For many cases iterating 1000 or 1000000 times and checking consistency of the answers is reasonable. This is your only option if you are also looking to check some required distribution across a range.
This might look something like:
for (int i = 0; i < 1000000; i++)
assertTrue(isValid(new RandomVal()));
If you want to check that all your characters appear at least once:
assertEquals(26 * 2 + 9, IntStream.range(0, 1000000)
.mapToObj(n -> stringBuilder(6))
.flatMap(String::chars)
.collect(Collectors.toSet())
.size());
This uses Java 8 and essentially adds every character (as an integer) to the set and then checks how large it is afterwards.
Using a mocking framework (such as Mockito) to check the result is the expected one for specific outputs from whatever you are using to generate randomness. This is the best way to test that you get the correct result boundary conditions (i.e. the generator returning results at each end of its range).
This might look something like:
Random mockRandom = mock(Random.class);
when(mockRandom.nextFloat()).thenReturn(0.0f);
assertTrue(isValid(new RandomVal(mockRandom));
when(mockRandom.nextFloat()).thenReturn(1.0f - Float.MIN_VALUE);
assertTrue(isValid(new RandomVal(mockRandom));
For completeness it's worth doing both of these.
If I understand your problem resolution is simple
int minRange = 999999; //improbable big value
int maxRange = -999999; //improbable low value
for (int i = 0; i < 100000; i++) {
int result = item.randomDigits();
minRange = Math.min(result, minRange);
maxRange = Math.max(result, maxRange);
}
Please try it.
If you don't like Math library you can of course do it without it
for (int i = 0; i < 100000; i++) {
int result = item.randomDigits();
if (result < minRange) {
minRange = result;
}
if (result > maxRange) {
maxRange = result;
}
}

Verifying correctness of FFT algorithm

Today I wrote an algorithm to compute the Fast Fourier Transform from a given array of points representing a discrete function. Now I'm trying to test it to see if it is working. I've tried about a dozen different input sets, and they seem to match up with examples I've found online. However, for my final test, I gave it the input of cos(i / 2), with i from 0 to 31, and I've gotten 3 different results based on which solver I use. My solution seems to be the least accurate:
Does this indicate a problem with my algorithm, or is it simply a result of the relatively small data set?
My code is below, in case it helps:
/**
* Slices the original array, starting with start, grabbing every stride elements.
* For example, slice(A, 3, 4, 5) would return elements 3, 8, 13, and 18 from array A.
* #param array The array to be sliced
* #param start The starting index
* #param newLength The length of the final array
* #param stride The spacing between elements to be selected
* #return A sliced copy of the input array
*/
public double[] slice(double[] array, int start, int newLength, int stride) {
double[] newArray = new double[newLength];
int count = 0;
for (int i = start; count < newLength && i < array.length; i += stride) {
newArray[count++] = array[i];
}
return newArray;
}
/**
* Calculates the fast fourier transform of the given function. The parameters are updated with the calculated values
* To ignore all imaginary output, leave imaginary null
* #param real An array representing the real part of a discrete-time function
* #param imaginary An array representing the imaginary part of a discrete-time function
* Pre: If imaginary is not null, the two arrays must be the same length, which must be a power of 2
*/
public void fft(double[] real, double[] imaginary) throws IllegalArgumentException {
if (real == null) {
throw new NullPointerException("Real array cannot be null");
}
int N = real.length;
// Make sure the length is a power of 2
if ((Math.log(N) / Math.log(2)) % 1 != 0) {
throw new IllegalArgumentException("The array length must be a power of 2");
}
if (imaginary != null && imaginary.length != N) {
throw new IllegalArgumentException("The two arrays must be the same length");
}
if (N == 1) {
return;
}
double[] even_re = slice(real, 0, N/2, 2);
double[] odd_re = slice(real, 1, N/2, 2);
double[] even_im = null;
double[] odd_im = null;
if (imaginary != null) {
even_im = slice(imaginary, 0, N/2, 2);
odd_im = slice(imaginary, 1, N/2, 2);
}
fft(even_re, even_im);
fft(odd_re, odd_im);
// F[k] = real[k] + imaginary[k]
// even odd
// F[k] = E[k] + O[k] * e^(-i*2*pi*k/N)
// F[k + N/2] = E[k] - O[k] * e^(-i*2*pi*k/N)
// Split complex arrays into component arrays:
// E[k] = er[k] + i*ei[k]
// O[k] = or[k] + i*oi[k]
// e^ix = cos(x) + i*sin(x)
// Let x = -2*pi*k/N
// F[k] = er[k] + i*ei[k] + (or[k] + i*oi[k])(cos(x) + i*sin(x))
// = er[k] + i*ei[k] + or[k]cos(x) + i*or[k]sin(x) + i*oi[k]cos(x) - oi[k]sin(x)
// = (er[k] + or[k]cos(x) - oi[k]sin(x)) + i*(ei[k] + or[k]sin(x) + oi[k]cos(x))
// { real } { imaginary }
// F[k + N/2] = (er[k] - or[k]cos(x) + oi[k]sin(x)) + i*(ei[k] - or[k]sin(x) - oi[k]cos(x))
// { real } { imaginary }
// Ignoring all imaginary parts (oi = 0):
// F[k] = er[k] + or[k]cos(x)
// F[k + N/2] = er[k] - or[k]cos(x)
for (int k = 0; k < N/2; ++k) {
double t = odd_re[k] * Math.cos(-2 * Math.PI * k/N);
real[k] = even_re[k] + t;
real[k + N/2] = even_re[k] - t;
if (imaginary != null) {
t = odd_im[k] * Math.sin(-2 * Math.PI * k/N);
real[k] -= t;
real[k + N/2] += t;
double t1 = odd_re[k] * Math.sin(-2 * Math.PI * k/N);
double t2 = odd_im[k] * Math.cos(-2 * Math.PI * k/N);
imaginary[k] = even_im[k] + t1 + t2;
imaginary[k + N/2] = even_im[k] - t1 - t2;
}
}
}
Validation
look here: slow DFT,iDFT at the end is mine slow implementation of DFT and iDFT they are tested and correct. I also used them for fast implementations validation in the past.
Your code
stop recursion is wrong (you forget to set the return element) mine looks like this:
if (n<=1) { if (n==1) { dst[0]=src[0]*2.0; dst[1]=src[1]*2.0; } return; }
so when your N==1 set the output element to Re=2.0*real[0], Im=2.0*imaginary[0] before return. Also I am a bit lost in your complex math (t,t1,t2) and to lazy to analyze.
Just to be sure here is mine fast implementation. It need too much things from class hierarchy so it will not be of another use for you then visual comparison to your code.
My Fast implementation (cc means complex output and input):
//---------------------------------------------------------------------------
void transform::DFFTcc(double *dst,double *src,int n)
{
if (n>N) init(n);
if (n<=1) { if (n==1) { dst[0]=src[0]*2.0; dst[1]=src[1]*2.0; } return; }
int i,j,n2=n>>1,q,dq=+N/n,mq=N-1;
// reorder even,odd (buterfly)
for (j=0,i=0;i<n+n;) { dst[j]=src[i]; i++; j++; dst[j]=src[i]; i+=3; j++; }
for ( i=2;i<n+n;) { dst[j]=src[i]; i++; j++; dst[j]=src[i]; i+=3; j++; }
// recursion
DFFTcc(src ,dst ,n2); // even
DFFTcc(src+n,dst+n,n2); // odd
// reorder and weight back (buterfly)
double a0,a1,b0,b1,a,b;
for (q=0,i=0,j=n;i<n;i+=2,j+=2,q=(q+dq)&mq)
{
a0=src[j ]; a1=+_cos[q];
b0=src[j+1]; b1=+_sin[q];
a=(a0*a1)-(b0*b1);
b=(a0*b1)+(a1*b0);
a0=src[i ]; a1=a;
b0=src[i+1]; b1=b;
dst[i ]=(a0+a1)*0.5;
dst[i+1]=(b0+b1)*0.5;
dst[j ]=(a0-a1)*0.5;
dst[j+1]=(b0-b1)*0.5;
}
}
//---------------------------------------------------------------------------
dst[] and src[] are not overlapping !!! so you cannot transform array to itself .
_cos and _sin are precomputed tables of cos and sin values (computed by init() function like this:
double a,da; int i;
da=2.0*M_PI/double(N);
for (a=0.0,i=0;i<N;i++,a+=da) { _cos[i]=cos(a); _sin[i]=sin(a); }
N is power of 2 (zero padded size of data set) (last n from init(n) call)
Just to be complete here is mine complex to complex slow version:
//---------------------------------------------------------------------------
void transform::DFTcc(double *dst,double *src,int n)
{
int i,j;
double a,b,a0,a1,_n,b0,b1,q,qq,dq;
dq=+2.0*M_PI/double(n); _n=2.0/double(n);
for (q=0.0,j=0;j<n;j++,q+=dq)
{
a=0.0; b=0.0;
for (qq=0.0,i=0;i<n;i++,qq+=q)
{
a0=src[i+i ]; a1=+cos(qq);
b0=src[i+i+1]; b1=+sin(qq);
a+=(a0*a1)-(b0*b1);
b+=(a0*b1)+(a1*b0);
}
dst[j+j ]=a*_n;
dst[j+j+1]=b*_n;
}
}
//---------------------------------------------------------------------------
I'd use something authoritative like Wolfram Alpha to verify.
If I evalute cos(i/2) for 0 <= i < 32, I get this array:
[1,0.878,0.540,0.071,-0.416,-0.801,-0.990,-0.936,-0.654,-0.211,0.284,0.709,0.960,0.977,0.754,0.347,-0.146,-0.602,-0.911,-0.997,-0.839,-0.476,0.004,0.483,0.844,0.998,0.907,0.595,0.137,-0.355,-0.760,-0.978]
If I give that as input to Wolfram Alpha's FFT function I get this result.
The plot that I get looks symmetric, which makes sense. The plot looks nothing like any of the ones you supplied.

Java: simplest integer hash

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.
HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.
[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.
I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}
The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

Shifting a Java BitSet

I am using a java.util.BitSet to store a dense vector of bits.
I want to implement an operation that shifts the bits right by 1, analogous to >>> on ints.
Is there a library function that shifts BitSets?
If not, is there a better way than the below?
public static void logicalRightShift(BitSet bs) {
for (int i = 0; (i = bs.nextSetBit(i)) >= 0;) {
// i is the first bit in a run of set bits.
// Set any bit to the left of the run.
if (i != 0) { bs.set(i - 1); }
// Now i is the index of the bit after the end of the run.
i = bs.nextClearBit(i); // nextClearBit never returns -1.
// Clear the last bit of the run.
bs.clear(i - 1);
// 0000111100000...
// a b
// i starts off the loop at a, and ends the loop at b.
// The mutations change the run to
// 0001111000000...
}
}
That should do the trick:
BitSet shifted = bs.get(1, bs.length());
It will give you a bitset equal to the orginial one, but without the lower-most bit.
EDIT:
To generalize this to n bits,
BitSet shifted = bs.get(n, Math.max(n, bs.length()));
An alternative which is probably more efficient would be to work with the underlying long[].
Use bitset.toLongArray() to get the underlying data. Shift those longs accordingly, then create a new BitSet via BitSet.valueOf(long[]) You'll have to be very careful shifting the underlying longs, as you will have to take the low order bit and shift it into the high order bit on the next long in the array.
This should let you use the bit shift operations native on your processor to move 64 bits at a time, as opposed to iterating through each one separately.
EDIT: Based on Louis Wasserman's comment. This is only available in Java 1.7 API. Didn't realize that when I wrote it.
Please find this code block where BitSet is "left-shifted"
/**
* Shift the BitSet to left.<br>
* For example : 0b10010 (=18) => 0b100100 (=36) (equivalent to multiplicate by 2)
* #param bitSet
* #return shifted bitSet
*/
public static BitSet leftShiftBitSet(BitSet bitSet) {
final long maskOfCarry = 0x8000000000000000L;
long[] aLong = bitSet.toLongArray();
boolean carry = false;
for (int i = 0; i < aLong.length; ++i) {
if (carry) {
carry = ((aLong[i] & maskOfCarry) != 0);
aLong[i] <<= 1;
++aLong[i];
} else {
carry = ((aLong[i] & maskOfCarry) != 0);
aLong[i] <<= 1;
}
}
if (carry) {
long[] tmp = new long[aLong.length + 1];
System.arraycopy(aLong, 0, tmp, 0, aLong.length);
++tmp[aLong.length];
aLong = tmp;
}
return BitSet.valueOf(aLong);
}
You can use BigInteger instead of BitSet. BigInteger already has ShiftRight and ShiftLeft.
These functions mimic the << and >>> operators, respectively.
/**
* Shifts a BitSet n digits to the left. For example, 0b0110101 with n=2 becomes 0b10101.
*
* #param bits
* #param n the shift distance.
* #return
*/
public static BitSet shiftLeft(BitSet bits, int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
long[] words = bits.toLongArray();
// Do the shift
for (int i = 0; i < words.length - 1; i++) {
words[i] >>>= n; // Shift current word
words[i] |= words[i + 1] << (64 - n); // Do the carry
}
words[words.length - 1] >>>= n; // shift [words.length-1] separately, since no carry
return BitSet.valueOf(words);
}
/**
* Shifts a BitSet n digits to the right. For example, 0b0110101 with n=2 becomes 0b000110101.
*
* #param bits
* #param n the shift distance.
* #return
*/
public static BitSet shiftRight(BitSet bits, int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
long[] words = bits.toLongArray();
// Expand array if there will be carry bits
if (words[words.length - 1] >>> (64 - n) > 0) {
long[] tmp = new long[words.length + 1];
System.arraycopy(words, 0, tmp, 0, words.length);
words = tmp;
}
// Do the shift
for (int i = words.length - 1; i > 0; i--) {
words[i] <<= n; // Shift current word
words[i] |= words[i - 1] >>> (64 - n); // Do the carry
}
words[0] <<= n; // shift [0] separately, since no carry
return BitSet.valueOf(words);
}
You can look at the BitSet toLongArray and the valueOf(long[]).
Basically get the long array, shift the longs and construct a new BitSet from the shifted array.
In order to achieve better performance you can extend java.util.BitSet implementation and avoid unnecessary array copying. Here is implementation (I've basically reused Jeff Piersol implementation):
package first.specific.structure;
import java.lang.reflect.Field;
import java.util.BitSet;
public class BitSetMut extends BitSet {
private long[] words;
private static Field wordsField;
static {
try {
wordsField = BitSet.class.getDeclaredField("words");
wordsField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
}
}
public BitSetMut(final int regLength) {
super(regLength);
try {
words = (long[]) wordsField.get(this);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
public void shiftRight(int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
if (words.length > 0) {
ensureCapacity(n);
// Do the shift
for (int i = words.length - 1; i > 0; i--) {
words[i] <<= n; // Shift current word
words[i] |= words[i - 1] >>> (64 - n); // Do the carry
}
words[0] <<= n; // shift [0] separately, since no carry
// recalculateWordInUse() is unnecessary
}
}
private void ensureCapacity(final int n) {
if (words[words.length - 1] >>> n > 0) {
long[] tmp = new long[words.length + 3];
System.arraycopy(words, 0, tmp, 0, words.length);
words = tmp;
try {
wordsField.set(this, tmp);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
}
With java SE8, it can be achieved more concise way:
BitSet b = new BitSet();
b.set(1, 3);
BitSet shifted = BitSet.valueOf(Arrays.stream(
b.toLongArray()).map(v -> v << 1).toArray());
I was trying to figure out how to use LongBuffer to do so but not quite got it to work. Hopefully, someone who is familiar with low level programming can point out a solution.
Thanks in advance!!!

Categories

Resources