Fastest way to generate a random double number in java - java

In a project in which I'm working for, I'm required to either generate n random double numbers (depending from what the input file says) or converting them to doubles if I have them from my input file. Those numbers should have only 2 decimals after the comma (ex.: 0.98).
I know that in Java 8, there are 2 ways of doing this:
Java 8 way: nthNumber = Double.parseDouble(new DecimalFormat("#.##").format(ThreadLocalRandom.current().nextDouble(0,1)).replace(",","."));
Old fashion way: nthNumber = Double.parseDouble(new DecimalFormat("#.##").format(new Random().nextDouble()).replace(",", "."));
Asymptotically speaking, which is the fastest? From my poor knowledge of A.D.S., I'd say it would be the same time (O(n)?) but I'm not 100% sure
Aside from these two ways, are there any other ways to generate random doubles between 0 and 1 which are faster, asymptotically speaking, than my proposals? (rather, are there methods that can do everything in O(n) or O(1) ?)
Thank you in advance to everyone who will spend a minute to answer to this question of mine

Both of your approaches use strings as an intermediate representation, this will be quite inefficient (memory allocation, string parsing, string formatting are all relatively slow operations. You probably also want to avoid allocating multiple instances of Random.
Given that you only want two decimal digits, why not create an integer in the range of 0..99 and divide it by 100.0?
Random random = new Random(); // Only one instance needed.
for (int n = 0; n < total; n++) {
double nthRandomNumber = random.nextInt(100) / 100.0;
}

Your code looks complicated.
Did you consider the following:
DecimalFormat decimalFormat = new DecimalFormat("0.00");
String twoDigitRandom = decimalFormat.format(Math.random());
Reference:
https://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
Edit: Added after the comment:
If you would like to control the number of digits and not to have a String as end result, then I would advise not to use Double, try BigDecimal instead:
MathContext m = new MathContext(3);
BigDecimal randomWithTwoDigits = new BigDecimal(Math.random(), m);

Related

I am trying to divide a 19 digit number by 100 (19 digit number/100) in java

I am trying to divide a 19 digit number by 100, i.e. 19 digit number/100, in java. It can be divisible using long data type but I'm not getting the full value as 17 digits and a decimal point followed by another 2 digits. Instead, I'm only getting 17 digits as it was a long data type so I need that digit like mathematical expression.
long cardValue = ("1234567891234567891");
long divide = (cardValue/100);
System.out.println(divide);
Output: 12345678912345678
I need output as 12345678912345678.91
longs are large integers, and when you divide one by another you use integer division, which omits everything right of the decimal point.
You could use a BigDecimal instead:
BigDecimal divide = new BigDecimal(String.valueOf(cardValue)).divide(new BigDecimal(100));
Firstly, you are doing integer division, and then expecting a decimal value. In Java, 1234 / 10 results in 123, and not 123.4. If you want a decimal result, make one of the values decimal, i.e., 1234.0 / 10 or 1234 / 10.0. This will yield 123.4
As of your problem, since the number is very large, using BigDecimal is a better idea (not BigInteger, as it will again perform integer division, while you want a decimal result). So, try
BigDecimal b = new BigDecimal("1234567891234567891");
BigDecimal res = b.divide(new BigDecimal("100"));
Or you can do a one-liner as
new BigDecimal("1234567891234567891").divide(new BigDecimal("100"))
In first, res = 12345678912345678.91, and the other will also result in the same.
Note : Although BigInteger and BigDecimal are all included in java.math package, but if it raises an error, import it by using
import java.math.BigDecimal;
Integer and long don't have decimal point.
Instead, use double.
double a = 123456789.00
double answer = (a/100.00)
Refer primitive data types in java.
If you want to get the string and want to dive, then use parseDouble() method to convert it to double. After this step perform division.
The divide variable is long type, that means no decimal fractions, just integer values. If you use double, you can obtain decimals, but that type don't have the precision you need in this case because it gives up to 15 significant numbers.
Your only solution is to use BigDecimal class. You can obtain whatever digit numbers you want. We used it for Banks and accounting applications, and is easy to understand how to work with it.
HTH

How do I store astronomically huge numbers into variables?

I'm still new to Java, and one of the ideas I had to make things more interesting is trying to make an algorithm that would convert numbers into letters (1000 = 1k // 1.000.000 = 1M // 1E+15 = 1aa..it would be an optimizer for a mobile game) , but turn out even double type variables has a pretty small limit compared to the numbers I want to work with (i.e 9.48E+3048).
Any ideas on how to approach this issue?
import java.math.BigInteger;
...
BigInteger myint = new BigInteger("5");
myint = myint.add(new BigInteger("7")); // 12
BigIntegers are immutable (They can't change), so the process is simply to .add, .multiply, etc, to get new numbers, and then overwrite variables as shown above. They will hold arbitrarily large numbers. All other functionality can be found here.
You will want to avoid converting integer to string as it will be too slow for numbers that large. Make a custom method to convert the most significant binary digits into the strings you desire (1k, 1M, 1aa, etc).
An alternative is hold two doubles in a (mantissa, exp) format, just as double does internally. After every operation, move the mantissa's exponent into the exponent variable with exp = this.getExponent(), mantissa = this.getMantissa(). getExponent could return something like floor(log(mantissa)) + exp, and getMantissa could return mantissa / nextLowerPowerOfTen(mantissa). This will give you 10^(10^3048), with 15 digits accuracy in the mantissa and 15 digits accuracy in the exponent.

Arithmetic mistakes when dealing with large numbers in java

I'm working with some arithmetic operations in Java which need to process very large numbers.
See this simple code snippet:
// A = a^k mod p
double k = 96 , a = 13 , p = 353 ;
double A = (Math.pow(a,k))%p;
System.out.println(A);
This prints 29.0.
When I use my windows calculator, it returns 58.0 for (13^96) % 353.
I know that the calculator is correct.
Why does this Java code print an incorrect result?
Explanation
Well, Math.pow probably does not do what you think it does. This is not your fault, it's practically lying to you. It returns a double that is reasonably close to 13^96, but not exactly. Since we are talking a number around 10^107 here, a small relative change means an absolute change far larger than 353. So, all bets about this are off.
Example
To put more numbers to this, practically the same problem arises when we use decimal scientific notation: The quotient is practically one but the difference is around 2^91.
In general, floating point numbers are unsuitable for integer arithmetic, you are practically bound to get these problems.
Solution
While a big integer lib would work, there is a more grounded way to approach this: Perform binary exponentiation and take the modulus each step.
In case you're a beginner, this will teach you more than the black box of some big int lib.
The calcul 13^96 result in the number :
86808413954902578113899124146033582025796522106191700214004730205740649831517648547259748010923363334343041
which requires too much precision to be stored in a double type
You can do this with BigInteger :
BigInteger bK = new BigInteger("96");
BigInteger bA = new BigInteger("13");
BigInteger bP = new BigInteger("353");
BigInteger res = bA.modPow(bK, bP); // same as res = bA.pow(96).mod(bP);
System.out.println(res); // 58

How to shift 4 decimal places in a number using DecimalFormat

I am trying to convert $11,120.6 million to 1.12 billion. My question is how to shift by 4 decimal places every time after the decimal point since I will be inserting values dynamically in excel.
Original title was a bit misleading, so my answer provides more than one way of accomplishing this task. First part reflects the answer to the new title.
11,120.6 shifted by four decimal places to the left will not create 1.12; more like 1.112 or 1.11 (depending on the number of decimal places). But anyways, here are some thoughts:
DecimalFormat way:
float num = 11120.6;
DecimalFormat numFormat = new DecimalFormat("#.00");
System.out.println(numFormat.format(num));
If it's purely visual, you can just do something like this:
float num = 11120.6;
System.out.println(String.format("%.2f", num));
That one will give you two decimal places to the right of the decimal point, producing 1.11.
Or how about something like this?
float num = 11120.6;
num /= 10000.0;
This will give you 1.11206.
You can create if else logic or something similar to divide/multiple by an appropriate amount, based on the number, i.e.:
if (num >= 10)
{
num /= 10.0;
}
else if (num >= 100)
{
num /= 100.0;
}
...etc...
You can also do something like this along with the similar logic to above:
BigDecimal num = new BigDecimal("11120.6");
num = num.movePointRight(-4);
Unless someone can think of a better way you'll also need to know that the number before was in millions representation and the new number is in billions. Store it in a separate variable as an enumeration, perhaps.
Something else you can do, but it's not very efficient, is what we did in my C++ class in college when we were messing around. You can create several arrays or lists (depending on what it is that you do) for certain number sizes. When you want to display a number of say... listBillions, you'd divide any number from that list by 1000000000.0, or format it as a string. So, in the the end you have your lists of dozens, hundreds, thousands, etc., and you'll always know that listBillions[i] can be nothing but a billion in whatever form it is being displayed.

How to print a large number with exponential notation?

If I have a number 52000000000, and I want to print it out as 5.2E+9, how do I do that with printf?
Since it's a simple method I'll guide you through it.
You'll need two counters: one for the number itself (type double, let's call it 'num'), and one for the exponent (integer, let's call it exp). You'll need a while loop such that while num is greater than 10, divide num by 10 and increase exp by 1. So, something like 7600 should have num = 7.6, exp = 3.
Depending on your return type, you can return these values in numerous ways. A simple way would be to have return type string and return num+"E"+exp.
This can be done with printf("%.2g", 52000000000);
"g" is the conversion character for scientific notation for formatting, and ".2" specifies the precision.
You need to have a look at this : DecimalFormat
formatter = new DecimalFormat("0.#E0");
System.out.println(formatter.format(value));//value is where you store the number to be formatted

Categories