Generate unique string within specific length range - java

I faced some difficulties to figure out how to generate unique string within [1;200) range length. The code I've come up with attached below:
public static String generateRandString() {
String STRING_TOKENS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
StringBuilder stringBuilder = new StringBuilder();
Random random = new Random();
while(stringBuilder.length() <= 200) {
int index = (int) random.nextFloat() * STRING_TOKENS.length();
stringBuilder.append(STRING_TOKENS.charAt(index));
}
return stringBuilder.toString();
}
The Problem:
Requesting 20 generated strings returns every time "AAAAAAAA" string probably of 200 symbols length
Expected output:
A7898as7sd6as5da
as87asd67
768asjhg435GhA900324
2g2j3h4gjhgAKL*78a9dd879234
3B234
1
Some limitations:
No additional libraries (Google Guava or Apache Common)
JDK 1.6 only
Many thanks to your contribution!

Try this !!!
for (int i = 0; i < 10; i++)
System.out.println(randomString(ThreadLocalRandom.current().nextInt(0, 200)));
static String randomString(int len) {
String AB = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random rnd = new Random();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
If you want to generate unique string. You can use java.util.UUID
import java.util.UUID;
String uuid = UUID.randomUUID().toString();

Use int index = random.nextInt(STRING_TOKENS.length());
In Java 1.7 or later, the standard way to to generate a random int value, but in a specific range is as follows:
import java.util.concurrent.ThreadLocalRandom;
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
See javadoc
Before Java 1.7
int randomNum = random.nextInt((max - min) + 1) + min;

In your line (int) random.nextFloat() * STRING_TOKENS.length() your int cast will be applied only to random.nextFloat() and since this value is between 0.0 and 1.0 the result of that cast will almost allways be 0 and your whole value will be 0 as well (As 0 * X is 0).
Use parenthesis: (int) (random.nextFloat() * STRING_TOKENS.length()) to apply the cast to the whole expression.

This line:
int index = (int) random.nextFloat() * STRING_TOKENS.length();
Here, you cast random.nextFloat() to int before the multiplication, thus always ending up with 0 * something. Add some parentheses:
int index = (int) (random.nextFloat() * STRING_TOKENS.length());
Or better, use nextInt instead:
int index = random.nextInt(STRING_TOKENS.length());
If you also want to randomize the length of the string, roll another number for use in the condition in the while loop:
int max = random.nextInt(200);
while(stringBuilder.length() <= max) {

Others have talked about making random strings. For guaranteed uniqueness you could use the string's hash code. If two strings have different hash codes then they are guaranteed not to be the same. As each string is generated, put its hash code into a set/array/whatever. If the hash code is already there (unlikely but possible) then reject that particular string and generate an alternative.
I'm not sure what is available in Java 1.6, so I won't write any actual code, but the idea is not difficult to implement.

Related

Random number in Java where one number has higher odds

I understand that in Java I can generate a random number with the following code:
Random rand=new Random()
int x=rand.nextInt(1);
I am interested generating either the number zero or one. But I want that number one has 90% higher probability of of being generated than zero.
How can I achieve that?
thanks
EDIT:
Thanks everyone. It's working.
Generate a random number from 0 to 9. If the number is 0, you return zero. If the number is 1-9, you return one.
Heres a pretty compact way to express it
Random rand=new Random();
int x = ((rand.nextInt(10) == 0)) ? 0 : 1;
This would do it:
int result;
if (Math.random() < 0.9) {
result = 1;
}
else {
result = 0;
}
Or more concise:
int result = (Math.random() < 0.9) ? 1 : 0;
read nextInt(int) manual which says:
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence. The general contract of nextInt is that one int value in the specified range is pseudorandomly generated and returned. All n possible int values are produced with (approximately) equal probability. The method nextInt(int n) is implemented by class Random as if by:
change your code to
Random rand=new Random();
int x=rand.nextInt(10);
return (x == 0) ? 0 : 1;
then run it again
You can write it like this.
int x = (int) (Math.random() / 0.9); // 90% chance of 0
or
int x = (int) (Math.random() + 0.9); // 90% chance of 1

How to get a random between 1 - 100 from randDouble in Java?

Okay, I'm still fairly new to Java. We've been given an assisgnment to create a game where you have to guess a random integer that the computer had generated. The problem is that our lecturer is insisting that we use:
double randNumber = Math.random();
And then translate that into an random integer that accepts 1 - 100 inclusive. I'm a bit at a loss. What I have so far is this:
//Create random number 0 - 99
double randNumber = Math.random();
d = randNumber * 100;
//Type cast double to int
int randomInt = (int)d;
However, the random the lingering problem of the random double is that 0 is a possibility while 100 is not. I want to alter that so that 0 is not a possible answer and 100 is. Help?
or
Random r = new Random();
int randomInt = r.nextInt(100) + 1;
You're almost there. Just add 1 to the result:
int randomInt = (int)d + 1;
This will "shift" your range to 1 - 100 instead of 0 - 99.
The ThreadLocalRandom class provides the int nextInt(int origin, int bound) method to get a random integer in a range:
// Returns a random int between 1 (inclusive) & 101 (exclusive)
int randomInt = ThreadLocalRandom.current().nextInt(1, 101)
ThreadLocalRandom is one of several ways to generate random numbers in Java, including the older Math.random() method and java.util.Random class. The advantage of ThreadLocalRandom is that it is specifically designed be used within a single thread, avoiding the additional thread synchronization costs imposed by the other implementations. Therefore, it is usually the best built-in random implementation to use outside of a security-sensitive context.
When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.
Here is a clean and working way to do it, with range checks! Enjoy.
public double randDouble(double bound1, double bound2) {
//make sure bound2> bound1
double min = Math.min(bound1, bound2);
double max = Math.max(bound1, bound2);
//math.random gives random number from 0 to 1
return min + (Math.random() * (max - min));
}
//Later just call:
randDouble(1,100)
//example result:
//56.736451234
I will write
int number = 1 + (int) (Math.random() * 100);
double random = Math.random();
double x = random*100;
int y = (int)x + 1; //Add 1 to change the range to 1 - 100 instead of 0 - 99
System.out.println("Random Number :");
System.out.println(y);

How can I create a random BigDecimal in Java?

This question: How to generate a random BigInteger describes a way to achieve the same semantics as Random.nextInt(int n) for BigIntegers.
I would like to do the same for BigDecimal and Random.nextDouble().
One answer in the above question suggests creating a random BigInteger and then creating a BigDouble from it with a random scale. A very quick experiment shows this to be a very bad idea :)
My intuition is that using this method would require the integer to be scaled by something like n-log10(R), where n is the number of digits of precision required in the output and R is the random BigInteger. This should allow the correct number of digits to be present so that (for example) 1 -> 10^-64 and 10^64 -> 1.
The scaling value also needs to be chosen correctly for the result to fall in the range [0,1].
Has anyone done this before, and do they know if the results are correctly distributed? Is there a better way to achieve this?
EDIT: Thanks to #biziclop for correcting my understanding of the scale argument. The above isn't necessary, a constant scale factor has the desired effect.
For later reference, my (apparently working code) is:
private static BigDecimal newRandomBigDecimal(Random r, int precision) {
BigInteger n = BigInteger.TEN.pow(precision);
return new BigDecimal(newRandomBigInteger(n, r), precision);
}
private static BigInteger newRandomBigInteger(BigInteger n, Random rnd) {
BigInteger r;
do {
r = new BigInteger(n.bitLength(), rnd);
} while (r.compareTo(n) >= 0);
return r;
}
It's surely very easy... if I only knew what you want. For a uniformly distributed number in range [0, 1) and precision N decimal digits generate a uniform BigInteger less than 10*N and scale it down by 10*N.
I made a post about generating a random BigInteger Andy Turner's answer about generating a random BigInteger. I don't use this directly for generating a random BigDecimal. Essentially my concern is to use independent instances of Random to generate each digit in a number. One problem I noticed is that with Random there are only so many values of and particular number that you get in a row. Also the generation tries to maintain something of an even distribution of generated values. My solution depends on something storing an array or collection of Random instances and calling these. I think this is a good way of going about it and I am trying to find out, so am interested if anyone has any pointers or criticism of this approach.
/**
*
* #param a_Random
* #param decimalPlaces
* #param lowerLimit
* #param upperLimit
* #return a pseudo randomly constructed BigDecimal in the range from
* lowerLimit to upperLimit inclusive and that has up to decimalPlaces
* number of decimal places
*/
public static BigDecimal getRandom(
Generic_Number a_Generic_Number,
int decimalPlaces,
BigDecimal lowerLimit,
BigDecimal upperLimit) {
BigDecimal result;
BigDecimal range = upperLimit.subtract(lowerLimit);
BigDecimal[] rangeDivideAndRemainder =
range.divideAndRemainder(BigDecimal.ONE);
BigInteger rangeInt = rangeDivideAndRemainder[0].toBigIntegerExact();
BigInteger intComponent_BigInteger = Generic_BigInteger.getRandom(
a_Generic_Number,
rangeInt);
BigDecimal intComponent_BigDecimal =
new BigDecimal(intComponent_BigInteger);
BigDecimal fractionalComponent;
if (intComponent_BigInteger.compareTo(rangeInt) == 0) {
BigInteger rangeRemainder =
rangeDivideAndRemainder[1].toBigIntegerExact();
BigInteger fractionalComponent_BigInteger =
Generic_BigInteger.getRandom(a_Generic_Number, rangeRemainder);
String fractionalComponent_String = "0.";
fractionalComponent_String += fractionalComponent_BigInteger.toString();
fractionalComponent = new BigDecimal(fractionalComponent_String);
} else {
fractionalComponent = getRandom(
a_Generic_Number, decimalPlaces);
}
result = intComponent_BigDecimal.add(fractionalComponent);
result.add(lowerLimit);
return result;
}
/**
* Provided for convenience.
* #param a_Generic_BigDecimal
* #param decimalPlaces
* #return a random BigDecimal between 0 and 1 inclusive which can have up
* to decimalPlaces number of decimal places
*/
public static BigDecimal getRandom(
Generic_Number a_Generic_Number,
int decimalPlaces) {
//Generic_BigDecimal a_Generic_BigDecimal = new Generic_BigDecimal();
Random[] random = a_Generic_Number.get_RandomArrayMinLength(
decimalPlaces);
//System.out.println("Got Random[] size " + random.length);
String value = "0.";
int digit;
int ten_int = 10;
for (int i = 0; i < decimalPlaces; i++) {
digit = random[i].nextInt(ten_int);
value += digit;
}
int length = value.length();
// Tidy values ending with zero's
while (value.endsWith("0")) {
length--;
value = value.substring(0, length);
}
if (value.endsWith(".")) {
value = "0";
}
BigDecimal result = new BigDecimal(value);
//result.stripTrailingZeros();
return result;
}
I might be missing the obvious here but how about creating two random BigIntegers, one being the integer part, and the other the fractional? Obviously the range of the "fractional" bigint would be dictated by the precision you want to allow, which you can't get away from pinning down.
Update: This can be further simplified to work with just one random bigint. If you want a random number between 0 and n with k decimal precision (where k is a constant), you just generate a random number between 0 and n*10^k and divide it by 10^k.

generating function arguments in java

I'm very new to java and am working on my first Android app. I am using the webview demo as a template. I am trying to generate a random integer between 1 and 12 and then call a certain javascript function based on the result. Here's what I have:
int number = 1 + (int)(Math.random() * ((12 - 1) + 1));
number = (int) Math.floor(number);
String nextQuote = "javascript:wave" + number + "()";
mWebView.loadUrl(nextQuote);
So mWebView.loadUrl(nextQuote) will be the same as something like mWebView.loadUrl("javascript:wave1()")
I just want to know if what I have here is correct and will work the way I think it will. The application isn't responding as expected and I suspect this bit of code is the culprit.
The key statement are as follows:
int number = 1 + (int)(Math.random() * ((12 - 1) + 1));
number = (int) Math.floor(number);
The first statement gives the answer you need, but in a rather cumbersome way. Lets step through what happens:
((12 - 1) + 1) is 12. (This is evaluated at compile time ... )
Math.random() gives a double in the range 0.0D <= rd < 1.0D.
Math.random() * 12 gives a double in the range 0.0D <= rd < 12.0D.
The (int) cast converts the double to an int by rounding towards zero. In other words (int)(Math.random() * 12) will be a integer in the range 0 <= ri <= 11.
Finally you add 1 giving an integer in the range 1 <= ri <= 12.
W**5 :-)
A simpler and clearer version would be:
private static Random rand = new Random();
...
int number = 1 + rand.nextInt(12);
The second statement is (as far as I can tell) a noop. It implicitly converts an int to a double, gets the double form of largest integer that is less or equal to that double, and converts that back to an int. The result will always be identical to the original int.
Documention of Java Random Class
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Random.html
A good way to do this.
Random rand = new Random(); // does not have to be static but can be.
int number = rand.nextInt(12) + 1; // 1 to 12 Must use 12
// Range is 0-11 add 1: 1-12
String nextQuote = "javascript:wave" + number + "()";
mWebView.loadUrl(nextQuote);
** from Java doc ** Method: public int nextInt(int n)
"Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive)"

How to generate a random BigInteger value in Java?

I need to generate arbitrarily large random integers in the range 0 (inclusive) to n (exclusive). My initial thought was to call nextDouble and multiply by n, but once n gets to be larger than 253, the results would no longer be uniformly distributed.
BigInteger has the following constructor available:
public BigInteger(int numBits, Random rnd)
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2numBits - 1), inclusive.
How can this be used to get a random value in the range 0 - n, where n is not a power of 2?
Use a loop:
BigInteger randomNumber;
do {
randomNumber = new BigInteger(upperLimit.bitLength(), randomSource);
} while (randomNumber.compareTo(upperLimit) >= 0);
on average, this will require less than two iterations, and the selection will be uniform.
Edit: If your RNG is expensive, you can limit the number of iterations the following way:
int nlen = upperLimit.bitLength();
BigInteger nm1 = upperLimit.subtract(BigInteger.ONE);
BigInteger randomNumber, temp;
do {
temp = new BigInteger(nlen + 100, randomSource);
randomNumber = temp.mod(upperLimit);
} while (s.subtract(randomNumber).add(nm1).bitLength() >= nlen + 100);
// result is in 'randomNumber'
With this version, it is highly improbable that the loop is taken more than once (less than one chance in 2^100, i.e. much less than the probability that the host machine spontaneously catches fire in the next following second). On the other hand, the mod() operation is computationally expensive, so this version is probably slower than the previous, unless the randomSource instance is exceptionally slow.
The following method uses the BigInteger(int numBits, Random rnd) constructor and rejects the result if it's bigger than the specified n.
public BigInteger nextRandomBigInteger(BigInteger n) {
Random rand = new Random();
BigInteger result = new BigInteger(n.bitLength(), rand);
while( result.compareTo(n) >= 0 ) {
result = new BigInteger(n.bitLength(), rand);
}
return result;
}
The drawback to this is that the constructor is called an unspecified number of times, but in the worst case (n is just slightly greater than a power of 2) the expected number of calls to the constructor should be only about 2 times.
The simplest approach (by quite a long way) would be to use the specified constructor to generate a random number with the right number of bits (floor(log2 n) + 1), and then throw it away if it's greater than n. In the worst possible case (e.g. a number in the range [0, 2n + 1) you'll throw away just under half the values you create, on average.
Why not constructing a random BigInteger, then building a BigDecimal from it ?
There is a constructor in BigDecimal : public BigDecimal(BigInteger unscaledVal, int scale) that seems relevant here, no ? Give it a random BigInteger and a random scale int, and you'll have a random BigDecimal. No ?
Here is how I do it in a class called Generic_BigInteger available via:
Andy Turner's Generic Source Code Web Page
/**
* There are methods to get large random numbers. Indeed, there is a
* constructor for BigDecimal that allows for this, but only for uniform
* distributions over a binary power range.
* #param a_Random
* #param upperLimit
* #return a random integer as a BigInteger between 0 and upperLimit
* inclusive
*/
public static BigInteger getRandom(
Generic_Number a_Generic_Number,
BigInteger upperLimit) {
// Special cases
if (upperLimit.compareTo(BigInteger.ZERO) == 0) {
return BigInteger.ZERO;
}
String upperLimit_String = upperLimit.toString();
int upperLimitStringLength = upperLimit_String.length();
Random[] random = a_Generic_Number.get_RandomArrayMinLength(
upperLimitStringLength);
if (upperLimit.compareTo(BigInteger.ONE) == 0) {
if (random[0].nextBoolean()) {
return BigInteger.ONE;
} else {
return BigInteger.ZERO;
}
}
int startIndex = 0;
int endIndex = 1;
String result_String = "";
int digit;
int upperLimitDigit;
int i;
// Take care not to assign any digit that will result in a number larger
// upperLimit
for (i = 0; i < upperLimitStringLength; i ++){
upperLimitDigit = new Integer(
upperLimit_String.substring(startIndex,endIndex));
startIndex ++;
endIndex ++;
digit = random[i].nextInt(upperLimitDigit + 1);
if (digit != upperLimitDigit){
break;
}
result_String += digit;
}
// Once something smaller than upperLimit guaranteed, assign any digit
// between zero and nine inclusive
for (i = i + 1; i < upperLimitStringLength; i ++) {
digit = random[i].nextInt(10);
result_String += digit;
}
// Tidy values starting with zero(s)
while (result_String.startsWith("0")) {
if (result_String.length() > 1) {
result_String = result_String.substring(1);
} else {
break;
}
}
BigInteger result = new BigInteger(result_String);
return result;
}
For those who are still asking this question and are looking for a way to generate arbitrarily large random BigIntegers within a positive integer range, this is what I came up with. This random generator works without trying bunch of numbers until one fits the range. Instead it will generate a random number directly that will fit the given range.
private static BigInteger RandomBigInteger(BigInteger rangeStart, BigInteger rangeEnd){
Random rand = new Random();
int scale = rangeEnd.toString().length();
String generated = "";
for(int i = 0; i < rangeEnd.toString().length(); i++){
generated += rand.nextInt(10);
}
BigDecimal inputRangeStart = new BigDecimal("0").setScale(scale, RoundingMode.FLOOR);
BigDecimal inputRangeEnd = new BigDecimal(String.format("%0" + (rangeEnd.toString().length()) + "d", 0).replace('0', '9')).setScale(scale, RoundingMode.FLOOR);
BigDecimal outputRangeStart = new BigDecimal(rangeStart).setScale(scale, RoundingMode.FLOOR);
BigDecimal outputRangeEnd = new BigDecimal(rangeEnd).add(new BigDecimal("1")).setScale(scale, RoundingMode.FLOOR); //Adds one to the output range to correct rounding
//Calculates: (generated - inputRangeStart) / (inputRangeEnd - inputRangeStart) * (outputRangeEnd - outputRangeStart) + outputRangeStart
BigDecimal bd1 = new BigDecimal(new BigInteger(generated)).setScale(scale, RoundingMode.FLOOR).subtract(inputRangeStart);
BigDecimal bd2 = inputRangeEnd.subtract(inputRangeStart);
BigDecimal bd3 = bd1.divide(bd2, RoundingMode.FLOOR);
BigDecimal bd4 = outputRangeEnd.subtract(outputRangeStart);
BigDecimal bd5 = bd3.multiply(bd4);
BigDecimal bd6 = bd5.add(outputRangeStart);
BigInteger returnInteger = bd6.setScale(0, RoundingMode.FLOOR).toBigInteger();
returnInteger = (returnInteger.compareTo(rangeEnd) > 0 ? rangeEnd : returnInteger); //Converts number to the end of output range if it's over it. This is to correct rounding.
return returnInteger;
}
How does it work?
First it generates a String with random numbers with the same length as the maximum range. For example: with given range of 10-1000 it will generate some number between 0000 and 9999 as a String.
Then it creates BigDecimals to represent the maximum possible value (9999 in previous example) and minimum value (0) and converts the range parameter BigIntegers to BigDecimals. Also in this step to the given range maximum value is added 1 in order to correct rounding errors in the next step.
Then using this formula the generated random number is mapped to the given range:
(generated - inputRangeStart) / (inputRangeEnd - inputRangeStart) * (outputRangeEnd - outputRangeStart) + outputRangeStart
After that it will do a last check whether or not the mapped number fits the given range and sets it to the given range maximum if it doesn't. This is done in order to correct rounding errors.
Just use modular reduction
new BigInteger(n.bitLength(), new SecureRandom()).mod(n)
Compile this F# code into a DLL and you can also reference it in your C# / VB.NET programs
type BigIntegerRandom() =
static let internalRandom = new Random()
/// Returns a BigInteger random number of the specified number of bytes.
static member RandomBigInteger(numBytes:int, rand:Random) =
let r = if rand=null then internalRandom else rand
let bytes : byte[] = Array.zeroCreate (numBytes+1)
r.NextBytes(bytes)
bytes.[numBytes] <- 0uy
bigint bytes
/// Returns a BigInteger random number from 0 (inclusive) to max (exclusive).
static member RandomBigInteger(max:bigint, rand:Random) =
let rec getNumBytesInRange num bytes = if max < num then bytes else getNumBytesInRange (num * 256I) bytes+1
let bytesNeeded = getNumBytesInRange 256I 1
BigIntegerRandom.RandomBigInteger(bytesNeeded, rand) % max
/// Returns a BigInteger random number from min (inclusive) to max (exclusive).
static member RandomBigInteger(min:bigint, max:bigint, rand:Random) =
BigIntegerRandom.RandomBigInteger(max - min, rand) + min

Categories