in Java I have a random generator that generates random number from -2^63 to 2^63 and that is NOT the java.util.Random.
I need to generate random double in (0,1), this is what I've done so far:
return (seed/(double)(9223372036854775807L))/2+0.5;//seed is a random long
Is this right? Are there any numerical problem (underflow?)?
Could be better/faster?
Thank you.
I would use Math.scalb as the most efficient and ensures there is no funny behaviour due to rounding or representation error
double d = Math.scalb(seed >>> 1, -63);
You can only use 53 bits in a double so some will be discarded.
If you run
long seed = Long.MAX_VALUE;
System.out.println(Math.scalb(seed >>> 1, -63));
prints
0.5
With a seed of 0 you get 0.0
With a seed of -1 you get 1.0
I would prefer to see just a single division.
0.5+(seed/1.84467440737096E+19);
That said, you are going to run up against issues with floating point accuracy since you have 64 random integer bits which you then try to squeeze into 53 bits of double precision. You may be better off making a dedicated generator for floating point values, but I could not say for sure since I don't know your motivation.
The fastest way would probably just be to set the first three bits in your long to 0 and then use those bits to make a double.:
double rand = Double.longBitsToDouble(seed & 0x1FFFFFFFFFFFFFFFL);
This works by forcing the sign to positive, and exponent to be less than 0, which will cause the mantissa to be shifted right at least once. It gives an even distribution assuming all the ints in the long are completely random. Here is a full Java program that uses Random to generate random longs, and then this method to convert them to double's between 0 and 1:
import java.util.Random;
class Main{
public static void main(String[] args){
Random rand = new Random();
long seed = rand.nextLong();
double x = Double.longBitsToDouble(seed & 0x1FFFFFFFFFFFFFFFL);
System.out.println(x);
}
}
This is the output of 10 executions:
1.1211565592484309E-247
8.84224349357039E-242
6.956043405745214E-271
3.747746366809532E-232
9.302628573486166E-158
1.1440116527034282E-166
1.2574577719255876E-198
5.104999671234867E-269
3.360619724894072E-213
1.5654452507283312E-220
Edit
This gives a uniform distribution of all possible doubles between 0 and 1. Since there are many more small doubles you will likely never see a number close to 1. You can fix this by generating a new exponent based on the bits of the existing one, but you need a loop to do it, so it probably isn't the fastest method after factoring this in:
long exponent = 0;
for(int i = 52; (seed >>> i & 1) > 0; i++) exponent++;
double x = Double.longBitsToDouble(seed & 0x000FFFFFFFFFFFFFL | ((1022 - exponent) << 52));
0.4773960377161338
0.929045618651037
0.7183096209363845
0.33962049395497845
0.45568660174922454
0.11670190555677815
0.09371618427480996
0.8192870898479095
0.9365016017283178
0.11311614413193898
Not exactly. I think that easier way is to do the following:
new Random(seed).nextDouble()
Unless I'm misreading your need to have a random double from 0 to 1, Java's built in Math.random does just that. So you could avoid all the conversion you are currently doing.
Related
I have the following sage code that runs instantly (less than a second) and I am trying to convert it to Java (using Java's built-in BigInteger library). But I am not successful.
In short, I initialized N as a BigInteger and delta as double and in order to calculate power (BigInteger ^ double) I converted N to BigDecimal (i.e. new BigDecimal(BigInteger)) and then:
I used this approach but it is too slow (extremely slow).
I used this library but I lost too much precision.
I used this library but I got overflow exception.
N = 16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791
delta = 0.26
X = 2*floor(N^delta) # in sage, ^ operator means exponentiation
# similar to ** operator in python
print("X:" + str(x))
Output:
X:32803899270297070621193977210731234596426011189989730481205367370572340252530823123935195892838208219967066426399488721710159859316222019683979411877007525412864
What is the magic? How sage does this? How to convert this code to Java (and be able to get a similar result), there should be some solution.
You can use approach #1 with a workaround. The problem there is that BigFunctions.ln() is not very effective for numbers with large integer part (number of digits to the left of the decimal point). As a workaround I scaled the number so that it contained at most one digit in integer part and compensated that later by adding ln(10) * rescale * delta to the argument of exp().
You should also note that using new BigDecimal(double) constructor leads to loss of precision - read the javadoc for explanation. Instead you should use new BigDecimal(String) (especially if that double comes from some sort of configuration value), or BigDecimal.valueOf(double).
BigInteger N = new BigInteger("16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791");
double delta = 0.26;
// this scale is sufficient to get the exact integer part
// it is roughly equal to the number of digits in the result's integer part
final int SCALE = 170;
BigDecimal x = new BigDecimal(N);
BigDecimal y = BigDecimal.valueOf(delta);
int maxIntDigits = 1;
int intDigits = x.precision() - x.scale();
int rescale = Math.max(intDigits - maxIntDigits, 0);
BigDecimal rescaledX = x.scaleByPowerOfTen(-rescale);
BigDecimal z = BigFunctions.exp(
BigFunctions.ln(rescaledX, SCALE)
.add(BigFunctions.ln(BigDecimal.TEN, SCALE).multiply(BigDecimal.valueOf(rescale)))
.multiply(y),
SCALE)
.setScale(0, BigDecimal.ROUND_FLOOR)
.multiply(BigDecimal.valueOf(2));
System.out.println(z);
Output:
32803899270296656086551107648280231830313861082788744611797945239672375099902513857958219091523648839375388564236289659519690404775361188478777234501437677352644
When creating a range of numbers as follows,
float increment = 0.01f;
for (int i = 0; i < 100; i++) {
float value = i * increment;
System.out.println(value);
}
it is clear, that I will end up for some i with values like
0.049999997, which are no exact multiples of 0.01, due to rounding errors.
When I try the same with floats in the range of usual integers, I have never seen the same problem:
float increment = 1.0f; //Still a float but representing an int value
for (int i = 0; i < 100; i++) {
float value = i * increment;
System.out.println(value);
}
One could expect, that this also prints out e.g. 49.999999 instead of 50, which I never saw however.
I am wondering, whether I can rely on that for any value of i and any value of increment, as long as it represents an integer (although its type is float).
And if so, I would be interested in an explanation, why rounding errors can not happen in that case.
Integers in a certain range (about up to one million or so) can be represented exactly as a float. Therefore you don't get rounding errors when you work only with them.
This is because float is based on floating point notation.
In rude words it tries to represent your decimal number as a sum of fractions of power 2.
It means it will try to sum 1/2^n1 + 1/2^n2 + 1/2^n3 .... 1/2^nm until gets closes or exact value that you put.
For example (rude):
0.5 it will represent as 1/2
0.25 it will represent as 1/2²
0.1 it will represent as 1/2^4
but in this case it will mutiply the number by 1.600000023841858 (mantissa) and it will give a number closer but not equal to 1 (1/2^4 x 1.600000023841858 = 0,100000001
Now you can see why after some loops the value changes to nonsense values
For rich detail of how it works read floating points IEEE 754
If you want precision you should use for example a BigDecimal from Java that uses another architecture to represent decimal numbers.
Double has the same problem.
Check this tool to see the repressentation of floating point:
http://www.h-schmidt.net/FloatConverter/IEEE754.html
It doesn't really represent an integer. It's still a float that you're just attempting to add the value 1.0 to. You'll get rounding errors as soon as 1.0 underflows (whenever the exponent gets larger than zero).
I was wondering if I am able to set the accuracy of the random double numbers that I generate.
Random generator = new Random();
double randomIndex = generator.nextDouble()*10000;
That produces the random numbers within 10000.
How am I able to set the accuracy to 4?
A couple of things. First, you mean "precision", not "accuracy". Second, you need to clarify why you want to do this, because a correct answer will depend on it.
If all you want to do is display the numbers with that precision, it is a formatting issue. You can use, e.g. System.out.printf("%.4f", value) or String.format().
If you are trying to to generate numbers with that precision, you could approximate by doing something like (rounding left out for simplicity):
double value = (int)(generateor.nextDouble() * 10000.0) / 10000.0;
Or if you want your range to be 0-10000 instead of 0-1:
double value = (int)(generateor.nextDouble() * 100000000.0) / 10000.0;
Due to the way floating-point numbers are stored, that will not be exact, but perhaps it is close enough for your purposes. If you need exact, you would want to store as integers, e.g.:
int value = (int)(generator.nextDouble() * 10000.0);
Then you can operate on that internally, and display as:
System.out.printf("%.4f", value / 10000.0);
Adjust multiplication factor above if you meant you wanted your range to be 0-10000.
If you are merely trying to generate a number in [0, 10000), you can use Random.nextInt(int) with a range specified, or simply cast the value to an int as above (optionally rounding).
Random generator = new Random();
double randomIndex = generator.nextDouble()*10000;
randomIndex=Math.floor(randomIndex * 10000) / 10000;//this is the trick
If you want 4 digits after the decimal mark you can simply do the following:
Random generator = new Random();
double randomIndex = Math.floor(generator.nextDouble()*10000 * 10000) /10000;
Random generator = new Random();
double randomIndex = Double.parseDouble(new DecimalFormat("##.####")
.format(generator.nextDouble() * 10000));
Simply
double result = generator.nextLong() / 10000.0;
Note, hoewever, that you can never be sure that the number has exactly 4 decimals, whenever you hit a number that is not representable in a double.
Anyway, the requirement is silly, because a double simply does not have decimal positions. Hence, to request 4 of them makes no sense.
Here's my implementation of Fermat's little theorem. Does anyone know why it's not working?
Here are the rules I'm following:
Let n be the number to test for primality.
Pick any integer a between 2 and n-1.
compute a^n mod n.
check whether a^n = a mod n.
myCode:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
This is a list of primes less than 100000. Whenever I input in any of these numbers, instead of getting 'true', I get 'false'.
The First 100,008 Primes
This is the reason why I believe the code isn't working.
In java, a double only has a limited precision of about 15 to 17 digits. This means that while you can compute the value of Math.pow(a,n), for very large numbers, you have no guarantee you'll get an exact result once the value has more than 15 digits.
With large values of a or n, your computation will exceed that limit. For example
Math.pow(3, 67) will have a value of 9.270946314789783e31 which means that any digit after the last 3 is lost. For this reason, after applying the modulo operation, you have no guarantee to get the right result (example).
This means that your code does not actually test what you think it does. This is inherent to the way floating point numbers work and you must change the way you hold your values to solve this problem. You could use long but then you would have problems with overflows (a long cannot hold a value greater than 2^64 - 1 so again, in the case of 3^67 you'd have another problem.
One solution is to use a class designed to hold arbitrary large numbers such as BigInteger which is part of the Java SE API.
As the others have noted, taking the power will quickly overflow. For example, if you are picking a number n to test for primality as small as say, 30, and the random number a is 20, 20^30 = about 10^39 which is something >> 2^90. (I took the ln of 10^39).
You want to use BigInteger, which even has the exact method you want:
public BigInteger modPow(BigInteger exponent, BigInteger m)
"Returns a BigInteger whose value is (this^exponent mod m)"
Also, I don't think that testing a single random number between 2 and n-1 will "prove" anything. You have to loop through all the integers between 2 and n-1.
#evthim Even if you have used the modPow function of the BigInteger class, you cannot get all the prime numbers in the range you selected correctly. To clarify the issue further, you will get all the prime numbers in the range, but some numbers you have are not prime. If you rearrange this code using the BigInteger class. When you try all 64-bit numbers, some non-prime numbers will also write. These numbers are as follows;
341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, ...
https://oeis.org/a001567
161038, 215326, 2568226, 3020626, 7866046, 9115426, 49699666, 143742226, 161292286, 196116194, 209665666, 213388066, 293974066, 336408382, 376366, 666, 566, 566, 666 2001038066, 2138882626, 2952654706, 3220041826, ...
https://oeis.org/a006935
As a solution, make sure that the number you tested is not in this list by getting a list of these numbers from the link below.
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
The solution for C # is as follows.
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}
I am working on an exercise in Java. I am supposed to use / and % to extract digits from a number. The number would be something like 1349.9431. The output would be something like:
1349.9431
1349.943
1349.94
1349.9
I know this is a strange way to do but the lab exercise requires it.
Let's think about what you know. Let say you have the number 12345. What's the result of dividing 12345 by 10? What's the result of taking 12345 mod 10?
Now think about 0.12345. What's the result of multiplying that by 10? What's the result of that mod 10?
The key is in those answers.
if x is your number you should be able to do something like x - x%0.1 to get the 1349.9, then x - x%.0.01 to get 1349.94 and so on. I'm not sure though, doing mod on floats is kind of unusual to begin with, but I think it should work that way.
x - x%10 would definetly get you 1340 and x - x%100 = 1300 for sure.
Well the work will be done in background anyway, so why even bother, just print it.
float dv = 1349.9431f;
System.out.printf("%8.3f %8.2f %8.1f", dv, dv, dv);
Alternatively this could be archived with:
float dv = 1349.9431f;
System.out.println(String.format("%8.3f %8.2f %8.1f", dv, dv, dv));
This is a homework question so doing something the way you would actually do in the real world (i.e. using the format method of String as Margus did) isn't allowed. I can see three constraints on any answer given what is contained in your question (if these aren't actually constraints you need to reword your question!)
Must accept a float as an input (and, if possible, use floats exclusively)
Must use the remainder (%) and division (/) operator
Input float must be able to have four digits before and after the decimal point and still give the correct answer.
Constraint 1. is a total pain because you're going to hit your head on floating point precision quite easily if you have to use a number with four digits before and after the decimal point.
float inputNumber = 1234.5678f;
System.out.println(inputNumber % 0.1);
prints "0.06774902343743147"
casting the input float to a double casuses more headaches:
float one = 1234.5678f;
double two = (double) one;
prints "1234.5677490234375" (note: rounding off the answer will get you 1234.5677, which != 1234.5678)
To be honest, this had me really stumped, I spent way too much time trying to figure out how to get around the precision issue. I couldn't find a way to make this program work for 1234.5678f, but it does work for the asker's value of 1349.9431f.
float input = 1349.9431f;
float inputCopy = input;
int numberOfDecimalPoints = 0;
while(inputCopy != (int) inputCopy)
{
inputCopy = inputCopy * 10;
numberOfDecimalPoints++;
}
double inputDouble = (double) input;
double test = inputDouble * Math.pow(10, numberOfDecimalPoints);
long inputLong = Math.round(test);
System.out.println(input);
for(int divisor = 10; divisor < Math.pow(10, numberOfDecimalPoints); divisor = divisor * 10)
{
long printMe = inputLong - (inputLong % divisor);
System.out.println(printMe / Math.pow(10, numberOfDecimalPoints));
}
Of my three constraints, I've satisfied 1 (kind of), 2 but not 3 as it is highly value-dependent.
I'm very interested to see what other SO people can come up with. If the asker has parsed the instructions correctly, it's a very poor exercise, IMO.