a friend of mine at Uni, was wanting to generate a bunch of 13 digit numbers so he can test his sorting algorithms on, but was doing it a very long way around, so i've tried to use the following code to generate a settable number of 13 digit numbers.
public class random {
public static void main(String[] args) {
long intArray[] = new long[20]; // to generate more than 20 random numbers increase this and the 'i < 20' to the same number ie. 75
for(int i = 0; i < 20; i++) { // here
intArray[i] = numbGen();
}
for(int j = 0; j < intArray.length; j++) {
System.out.println(intArray[j]);
}
}
public static long numbGen() {
long numb = (long)(Math.random() * 10000000 * 1000000); // had to use this as int's are to small for a 13 digit number.
return numb;
}
}
my issue is now sometimes it will generate a couple of 12 digit numbers in the group of 20 and i want to find a way not to add the number to the array if it is not 13 digits. I've tried if statement but getting stuck on not being able to determine the length (individual characters) of the Long.
Thanks in Advance.
A simple solution:
while(test < 10000) {
long num = (long) (Math.random() * 100000000 * 1000000);
if(Long.toString(num).length() == 13) {
return num;
}
test++;
}
However, a better solution is this:
long number = (long) Math.floor(Math.random() * 9000000000000L) + 1000000000000L;
This will only generate random 13 digit numbers, and you don't need to check if there are more or less digits.
Note that this solution may not scale to a higher number of digits and may not return a perfect distribution of random numbers.
long min = 1000000000000L; //13 digits inclusive
long max = 10000000000000L; //14 digits exclusive
Random random = new Random()
long number = min+((long)(random.nextDouble()*(max-min)));
A generic integer based implementation would be:
public static long randomDigits(int digits) {
if (digits <= 0 || digits > 18) {
throw new IllegalArgumentException("A long can store the random of 18 full digits, you required: " + digits);
}
// use SecureRandom instead for truly random values
final Random r = new Random();
long randomNumber = r.nextInt(9) + 1;
for (int i = 1; i < digits; i++) {
randomNumber = randomNumber * 10L + (long) r.nextInt(10);
}
return randomNumber;
}
or use a shorter version for 13 digits that does not tax the RNG as much:
public static long thirteenRandomDigits() {
final Random r = new Random();
return 1_000_000_000L * (r.nextInt(9_000) + 1_000)
+ r.nextInt(1_000_000_000);
}
These solutions are better to using Math.random() because they don't rely on multiplication with a large number to generate the random values. A double only has 15-17 digits precision, which is very close to the 13 digits number it is multiplied with. This leads to unequal distributions of random numbers. Solutions based on Math.random() won't scale past 13 digits either.
The simple solution for the problem that you described:
public static long numbGen() {
while (true) {
long numb = (long)(Math.random() * 100000000 * 1000000); // had to use this as int's are to small for a 13 digit number.
if (String.valueOf(numb).length() == 13)
return numb;
}
}
This is not the most efficient or most random implementation of generating a 13-digit number but it answers your specific question.
ThreadLocalRandom is a good thing, introduced in Java 1.7
java.util.concurrent.ThreadLocalRandom
.current()
.nextLong(1000000000000L, 10000000000000L);
long randomNumber = 0;
long power = 1;
for(int i = 0; i < 12; i++) { // up to 12 not 13
Random r = new Random();
int randomInt = r.nextInt(10);
randomNumber += (power * randomInt);
power *= 10;
}
// here, the most stupid way to provide last digit to be not zero
Random r = new Random();
int randomInt = r.nextInt(9);
randomInt++;
randomNumber += (power * randomInt);
power *= 10;
First off, a Long doesn't have characters.
If you want to see if it has 13 digits, compare it to 999999999999L.
If you want to insure you have a value w/ 13 digits, get a random number between 0 and 8999999999999L (inclusive) (using the technique you already have to generate a random number in a range) and add it to 1000000000000L.
Why not we try with Unix timestamp in milliseconds.Because that will work for next 200 years and after that we need to only eliminate the trailing digit from the number.
Calendar.getInstance().get(Calendar.MILLISECOND);
and by using this method we don't need any loop or any condition and it will give me a unique number every time.
Related
How would you add digits to the beginning of a number (left hand side) without using a string?
I know that if you try this:
(Some psuedo code)
Let's say I try to make number 534
int current = 5;
int num = 0;
num = (num*10) +current;
then
int current = 3;
int num = 5
num = (num*10) + current;
would make: 53
then
int current = 4;
int num = 53;
num = (num*10) + current;
would make 534
It would keep adding numbers to the right hand side of the number.
However, I am a bit confused on how you would do the opposite. How would you add numbers on the left, so instead of 534 it makes 435?
int num = 123;
int digits = 456;
int powerOfTen = (int) Math.pow(10, (int) (Math.log10(digits) + 1));
int finalNum = digits * powerOfTen + num;
System.out.println(finalNum); // Output: 456123
The number of digits in digits is calculated using Math.log10 and Math.pow, and then used to determine the appropriate power of 10 to multiply digits by. The result is then added to num to obtain the final number with the added digits.
Multiply the digit to add by increasing powers of 10 before summing with the current number.
int num = 0, pow = 1;
num += 5 * pow;
pow *= 10;
num += 3 * pow;
pow *= 10;
num += 4 * pow; // num = 435 at this point
pow *= 10;
// ...
An example without the use of libraries could be this:
First, get the number of digits. Then calculate the number you have to add to your initial number. The sum of these two numbers is the result you're after.
private int addNumberInFrontOf(int initialNumber, int initialNumberToAdd){
int numberOfDigits = getDigits(initialNumber);
int getActualNumberToAdd = getNumberToAdd(initialNumberToAdd, numberOfDigits);
return initialNumber + getActualNumberToAdd;
}
To calculate the number of digits, you can count the number of times you can divide the initial number by 10. Notice you need to use a do-while loop because otherwise the loop wouldn't be triggered if your initial number was 0.
private int getDigits(int number) {
int count = 0;
do {
number = number / 10;
count += 1;
} while (number != 0);
return count;
}
Calculate the number you need to add to your initial number by multiplying the initial number to add with the magnitude. The magnitude simply is 1 multiplied with 10 for every digit in the initial number.
private int getNumberToAdd(int number, int numberOfDigits) {
int magnitude = 1;
for (int i = 0; i < numberOfDigits; i++) {
magnitude *= 10;
}
return number * magnitude;
}
For example, addNumberInFrontOf(456, 123) would result in 123456. Of course, this method won't work when you use positive and negative numbers combined.
You can use String for example.
public static int addLeft(int cur, int num) {
return num == 0 ? cur : Integer.parseInt(cur + String.valueOf(num));
}
In case you want to avoid working with String, you can use recursion instead.
public static int addLeft(int cur, int num) {
return num == 0 ? cur : addLeft(cur, num / 10) * 10 + num % 10;
}
You can use some math, in python
import math
def addLeft(digit, num):
return digit * 10 ** int(math.log10(num) + 1) + num
Note that this might fail for very large numbers on account of precision issues
>>> addLeft(2, 100)
2100
>>> addLeft(3, 99)
399
>>> addLeft(6, 99999999999999)
699999999999999
>>> addLeft(5, 999999999999999)
50999999999999999 (oops)
The assignment is to flip a coin until four heads in a row are seen and display all the results leading up to that. I keep getting the last error message I put in just in case it fell through. I have no idea what I messed up and was wondering if someone was able to help.
class Main {
public static void main(String[] args) {
int h = 2;
int t = 1;
int count = 0;
int result;
while (count<=4)
{
result = (int)Math.random()*2;
if (result == 2)
{
count++;
System.out.print("H ");
}
else if (result == 1)
{
count=0;
System.out.print("T ");
}
else
System.out.println("error");
}
}
}
(int)Math.random() * 2
is the same as
((int)Math.random()) * 2
Given that Math.random() returns a number at least zero but less than one, your expression is always going to be zero.
Put in parentheses:
(int) (Math.random() * 2)
But then, also look at the values of result in your conditionals: you will never generate 2.
You need to add 1 to have possible values of one or two:
result = (int) (Math.random() * 2 + 1);
You can use the Randomclass and boolean
Random random = new Random();
int count = 0;
while (count < 4) {
if (random.nextBoolean()) {
System.out.print("H");
count++;
} else {
count = 0;
System.out.print("T");
}
}
As the result of Math.random() is between 0 and 1 type casting it to int will remove the digits after decimal point and you'll always have zero as answer.
Below code will help you to generate a random number between min and max.
// define the range
int max = 2;
int min = 1;
int range = max - min + 1;
int rand = (int)(Math.random() * range) + min;
For an explanation of how this works you can put the min possible value of 0 and max possible of 0.99 and multiply both by any range, let's say 20 the answer will still be in between 1 to 20.8 which gets turned to 20 as it's not rounding off but directly type casting. Hence, this can give you a random number for any range.
I discovered the hard way that this method seems to fail miserably when you feed it a power of 2. Given two Random objects of different seeds, it seems that the first integer they return when asked to return an integer between 0 (inclusive) and and a power of two (exclusive) is always the same; the seeds don't matter. For example:
public static void main(String[] args) {
Random mRandom;
for (int i = 0; i < 10; i++) {
mRandom = new Random(i);
System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
}
}
Console:
11
11
11
11
11
11
11
11
11
11
I chose 2^4 arbitrarily, but it seems to work for any power of two. What's going on? Furthermore, how can I avoid this?
This problem occurs due to 2 reasons.
Same seed for Random class.
At nextInt(int n), if n is power of 2
1. Same seed for Random class.
Because, you have initiated new Random instance with new seed value which has influence on the nextInt value generation. According to Java docs of Random(long seed).
Creates a new random number generator using a single long seed. The seed is the initial value
of the internal state of the
pseudorandom number generator which is maintained by method next(int).
The invocation new Random(seed) is equivalent to:
Random rnd = new Random();
rnd.setSeed(seed);
If you try to generate random value, without new seed than it will generate real random value, even though new instance of Random class.
for (int i = 0; i < 10; i++) {
mRandom = new Random(); // Without seed
System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
}
Output: 2 1 12 4 3 9 9 8 2 9
2. At nextInt(int n), if n is power of 2
Besides this, Random#nextInt has effect of power of 2. If n is a power of 2 it will return (int)((n * (long)next(31)) >> 31) which will always same for same n. According to nextInt Algorithm,
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
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;
}
You could also use Math.random and Math.pow together for more simplicity if you wanted.
for (int i = 0; i < 10; i++) {
int pows = (int) Math.pow(2, 4);
int random = (int)(Math.random()*pows);
System.out.println(""+random);
}
I need to make a random number between 1 and 20, and based on that number (using "If - Then" statements), I need to set the image of an ImageView.
I know that in Objective-C, it goes like this:
int aNumber = arc4Random() % 20;
if (aNumber == 1) {
[theImageView setImage:theImage];
}
How can I do this in Java? I have seen it done this way, but I do not see how I can set the range of numbers (1-20, 2-7, ect).
int aNumber = (int) Math.random()
Docs are your friends
Random rand = new Random();
int n = rand.nextInt(20); // Gives n such that 0 <= n < 20
Documentation:
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
Thus, from this example, we'll have a number between 0 and 19
Math.random() returns an double from [0,1[.
Random.nextInt(int) returns an int from [0, int[.
You can try:
int aNumber = (int) (20 * Math.random()) + 1;
or
Random rand = new Random();
int n = rand.nextInt(20) + 1;
You can use Math.random() to generate a double between 0 and 1 non-inclusive. Android Javadoc here.
I am trying with below code to generate 10 digits unique random number. As per my req i have to create around 5000 unique numbers(ids). This is not working as expected. It also generates -ve numbers. Also sometimes one or two digits are missing in generated number resulting in 8 or 9 numbers not 10.
public static synchronized List generateRandomPin(){
int START =1000000000;
//int END = Integer.parseInt("9999999999");
//long END = Integer.parseInt("9999999999");
long END = 9999999999L;
Random random = new Random();
for (int idx = 1; idx <= 3000; ++idx){
createRandomInteger(START, END, random);
}
return null;
}
private static void createRandomInteger(int aStart, long aEnd, Random aRandom){
if ( aStart > aEnd ) {
throw new IllegalArgumentException("Start cannot exceed End.");
}
//get the range, casting to long to avoid overflow problems
long range = (long)aEnd - (long)aStart + 1;
logger.info("range>>>>>>>>>>>"+range);
// compute a fraction of the range, 0 <= frac < range
long fraction = (long)(range * aRandom.nextDouble());
logger.info("fraction>>>>>>>>>>>>>>>>>>>>"+fraction);
int randomNumber = (int)(fraction + aStart);
logger.info("Generated : " + randomNumber);
}
So you want a fixed length random number of 10 digits? This can be done easier:
long number = (long) Math.floor(Math.random() * 9_000_000_000L) + 1_000_000_000L;
Note that 10-digit numbers over Integer.MAX_VALUE doesn't fit in an int, hence the long.
I think the reason you're getting 8/9 digit values and negative numbers is that you're adding fraction, a long (signed 64-bit value) which may be larger than the positive int range (32-bit value) to aStart.
The value is overflowing such that randomNumber is in the negative 32-bit range or has almost wrapped around to aStart (since int is a signed 32-bit value, fraction would only need to be slightly less than (2^32 - aStart) for you to see 8 or 9 digit values).
You need to use long for all the values.
private static void createRandomInteger(int aStart, long aEnd, Random aRandom){
if ( aStart > aEnd ) {
throw new IllegalArgumentException("Start cannot exceed End.");
}
//get the range, casting to long to avoid overflow problems
long range = aEnd - (long)aStart + 1;
logger.info("range>>>>>>>>>>>"+range);
// compute a fraction of the range, 0 <= frac < range
long fraction = (long)(range * aRandom.nextDouble());
logger.info("fraction>>>>>>>>>>>>>>>>>>>>"+fraction);
long randomNumber = fraction + (long)aStart;
logger.info("Generated : " + randomNumber);
}
I don't know why noone realized that but I think the point is to generate "unique" random number which I am also trying to do that. I managed to generate 11 digits random number but I am not sure how to generate unique numbers. Also my approach is a little different. In this method I am appending number chars next to each other with for loop. Then returning long number.
public long generateID() {
Random rnd = new Random();
char [] digits = new char[11];
digits[0] = (char) (rnd.nextInt(9) + '1');
for(int i=1; i<digits.length; i++) {
digits[i] = (char) (rnd.nextInt(10) + '0');
}
return Long.parseLong(new String(digits));
}
I would use
long theRandomNum = (long) (Math.random()*Math.pow(10,10));
A general solution to return a 'n' digit number is
Math.floor(Math.random() * (9*Math.pow(10,n-1))) + Math.pow(10,(n-1))
For n=3, This would return numbers from 100 to 999 and so on.
You can even control the end range, i.e from 100 to 5xx but setting the "9" in the above equation "5" or any other number from 1-9
This is a utility method for generating a fixed length random number.
public final static String createRandomNumber(long len) {
if (len > 18)
throw new IllegalStateException("To many digits");
long tLen = (long) Math.pow(10, len - 1) * 9;
long number = (long) (Math.random() * tLen) + (long) Math.pow(10, len - 1) * 1;
String tVal = number + "";
if (tVal.length() != len) {
throw new IllegalStateException("The random number '" + tVal + "' is not '" + len + "' digits");
}
return tVal;
}
Maybe you are looking for this one:
Random rand = new Random();
long drand = (long)(rand.nextDouble()*10000000000L);
You can simply put this inside a loop.
this is for random number starting from 1 and 2 (10 digits).
public int gen() {
Random r = new Random(System.currentTimeMillis());
return 1000000000 + r.nextInt(2000000000);
}
hopefully it works.
Hi you can use the following method to generate 10 digit random number
private static int getRndNumber() {
Random random=new Random();
int randomNumber=0;
boolean loop=true;
while(loop) {
randomNumber=random.nextInt();
if(Integer.toString(randomNumber).length()==10 && !Integer.toString(randomNumber).startsWith("-")) {
loop=false;
}
}
return randomNumber;
}