How to generate random numbers which will provide proper results on division - java

How to generate random numbers which will provide proper results on division (i.e the results should round to exactly 1 or 2 places after the decimal point).
(e.g a whole number by a decimal number providing decimal results - I have given a set of sample inputs below)
2827 by 2.5 = 1130.8
1747 by 0.8 = 2183.75
425 by 0.4 = 1062.5
935 by 0.8 = 1168.75

res = input * random.nextInt (100) / 100.0;
Explanation:
You take a whole number n, and multiply it with something. If this something is a number like 34.56, we call the part before the decimal digit w (whole part) and the part behind .xy.
If you multiply this with n, you end with (n*w)+(n*(x/10))+n*(y/100). There will never be an fractional part 3 ciphers behind the dot - do you agree?
We can combine x and y to a single part, and say (n*w) + (n*(xy/100)), and xy is just the name for something from 0 to 100.
Since the part before the decimal dot can be arbitrary large, you can calculate it seperately, if you need something else than 0. But you have to define a range somehow. If you take an random Integer R for that part:
res = input * R * random.nextInt (100) / 100.0;
Do you need the divisor explicityl?
div = 100.0 / (R * random.nextInt (100));
Scala is always handy, when testing code fragmenst:
val r = util.Random
r: util.Random.type = scala.util.Random$#ce2f12
scala> def res (input: Int) = input * r.nextInt (100) / 100.0;
res: (input: Int)Double
scala> (1 to 20).map (res)
res338: scala.collection.immutable.IndexedSeq[Double] =
Vector(0.48, 1.58, 0.48, 2.8, 0.15, 1.98, 5.67, 3.36, 6.93, 6.0, 9.02, 0.48, 7.41, 6.44, 9.6, 1.92, 16.66, 5.94, 7.98, 18.4)

It is worth noting that all integers can be divided by 0.4, 0.8 or 2.5 and be represented to two decimal places. This is because it is the same as multiplying by 2.5, 1.25, and 0.4
However, if you have a divisor for which this is not true, you can do this in a loop.
double divisor = 2.4;
double factor = 100/divisor;
Random rand = new Random();
int maxValue = 1000;
double ERROR = 1e-14*maxValue;
for(int i=0;i<100;i++) {
long randNum;
do {
randNum = rand.nextInt(maxValue+1);
if (Math.abs(randNum * factor - (long) (randNum * factor)) > ERROR)
System.out.println("reject "+randNum + " => "+randNum/divisor);
} while(Math.abs(randNum * factor - (long) (randNum * factor)) > ERROR);
System.out.println(randNum + " => "+randNum/divisor);
prints
729 => 303.75
285 => 118.75
84 => 35.0
123 => 51.25
999 => 416.25
75 => 31.25
reject 727 => 302.9166666666667
reject 842 => 350.83333333333337
504 => 210.0
reject 368 => 153.33333333333334
441 => 183.75
579 => 241.25
165 => 68.75
This will generate random numbers until you have a number which is a multiple of 0.01.

If you want the result to 'round' to 2 decimal places (it's not really rounding, it's just a finite decimal representation with two decimal points), then just generate the divisor, and have the dividend always be 100, e.g.:
106250 / 100 = 1062.5
116875 / 100 = 1168.75
If you want more interesting dividends then divide the divisor and dividend. e.g. the first one could be any one of:
(/1): 106250 / 100 = 1062.5
(/2): 53125 / 50 = 1062.5
(/10): 10625 / 10 = 1062.5
(/4): 26562.5 / 25 = 1062.5
(/125): 850 / 0.8 = 1062.5

For me the dividend and divisor are both random numbers. I have to produce an answer which doesn't require rounding decimals beyond 2 decimal places.
If that is the case, the answer might be "there is no such number". Here's a little Java program I wrote to test this hypothesis:
import java.text.DecimalFormat;
public class Test {
public static void main(String[] args) {
double num = Math.PI;
DecimalFormat format = new DecimalFormat(
"####################################0." +
"00##############################");
while (true) {
for (int i = 1; i < Integer.MAX_VALUE; i++) {
double tmp = (i / num) * 100;
if (tmp == (long) tmp) {
System.err.println("Solution - " + i + " - " +
format.format(tmp) + " - " + format.format(num));
break;
}
}
pi = Math.nextAfter(num, 1);
}
System.err.println("No solution for " + format.format(num));
}
}
I ran this for 10 minutes (starting at PI), and didn't find any values of num that had no solution i. But I did observe that solutions can be very sparse. For instance:
Gotcha! - 179453441 - 5712180438.00 - 3.1415926535897714
It took 179 million attempts to find the solution for that divisor.

Related

Generate Random X.XXX numbers between [-2, 2]

x = rd.nextInt((4000) - 2000) / 1000.0;
This is generating numbers between [0, 2] to the thousandth decimal which is what I want, I just also need negative number so the range of numbers generated is between [-2, 2].
The problem you are facing is integer arithmetic, which truncates the fractional part of the result. Use rd.nextDouble() instead so the arithmetic results are double, which retains the fractional part.
However, to round to 1/100ths, you can use integer arthmetic to your advantage.
Your question has the text to the hundredth decimal, so here's that solution:
x = (int)(((rd.nextDouble() * 4) - 2) * 100) / 100d;
But your title mentions X.XXX, so here's that solution:
x = (int)(((rd.nextDouble() * 4) - 2) * 1000) / 1000d;
To unravel what's going on here:
generate random double between 0.000000 and 1.000000
multiply by the scale of the range, so we get a number between 0.000000 and 4.000000
subtract 2, so we get a number between -2.000000 and 2.000000
multiply by 1000, so we get a number between -2000.000000 and 2000.000000
cast to int to truncate the fraction, so we get a int between -2000 and 2000
divide by 1000d (which is a double), so we get a double between -2.000 and 2.000
Floating point numbers do not always have a precise number of digits. Also, the third decimal place is called thousandths (the hundredth decimal would be the second digit after the .). I think you know this because you are dividing by a thousand. So, step one: generate a single random value between 0 and 4 as a double. Step two: Subtract two and convert to a formatted String (so you can control the number of digits).
double d = (rd.nextDouble() * 4) - 2;
String x = String.format("%.3f", d);
You can generate a random float and then use a modulo to truncate it to the hundredth decimal place.
int min = -2;
int max = 2;
Random rand = new Random();
float ret = rand.nextFloat() * (max - min) + min;
return ret - (ret % 0.01);
You can generate random number on a range [0,4] and then simply subtract 2 from the result:
x = (rd.nextInt(4000) / 1000.0) - 2;

Java on double: How to properly implement 'd' or 'D if there are many numbers or an expression to calculate?

It's said that we should put 'd' or 'D' after the number when you're creating a double variable. But what if I'm calculating many numbers.
double div = (6 % 4) / 10; // result 0.2
System.out.println("answer: " + div); // output: 0.0
Obviously, I will get an unexpected answer which is supposed to be 0.2 NOT 0.0... Now if I put 'd' or 'D' after the numbers, I will get a proper answer.
double div = (6d % 4d) / 10d; // result 0.2
System.out.println("answer: " + div); // output: 0.2
Should I put 'd' on all numbers in one expression when using double variable? or putting 'd' in one number is enough?
double div = (6 % 4) / 10d; //0.2
Just use dot with numbers or one of them
Result = (6 % 4) / 10.0;
Resoun: dividing int / int = int , otherwise int / double = double

Pretty number formatting algorithm

Algorithm to convert an integer representing a number of bytes into an pretty format.
3 digits max (not counting decimal) - for eg like linux command line.
no leading or trailing zeroes
1K is 1000 bytes
Examples:
Correct
123B -> 123B
12300B -> 12.3K
1910000B -> 1.91M
1000000000B -> 1G
83123 = 83.1K (not 83K)
Incorrect
012K (should be 12K)
8.20M (should be 8.2M)
I would like to know what did I do wrong or is there an easy better way to solve this problem or if there are any bugs in my code.
Below is my solution (it works but I was not selected so I have not idea of what I did wrong) -
/*
* #Description - Function takes integer as input and returns the number in
* pretty format(Gigabyte, Megabytes, KiloBytes, Bytes) with maximum of 3
* digits
* #param integer to convert to pretty format
* #Assumptions - As mentioned in the problem set, 1000bytes = 1KB
* Value is rounded to the nearest valid value
* In java leading 0 in number is considered Octal, this function does not
* take care of octal to decimal conversion
* As 1G = 1,000,000,000B the loop will run maximum 3 times in worst case
* Its requires constant space O(1) to store the result
*/
static String fpretty(int num) {
int count = 0;
double div_result = (double) num;
String display = "";
/*
* Every time we divide by 1000 count is incremented from B->K->M->G
* Here two decimal places are preserved for cases like 1.05, 1.11
* The output result of this loop will have 1,2 or 3 digits with max
* two decimal places
*/
while(div_result > 999.5) {
div_result = div_result / 1000;
div_result = Math.round(div_result * 100.0) / 100.0;
count++;
}
// Get suffix B, K, M or G
String measure = getUnit(count);
// If decimal places is all zeros OR result has 3 digits
if(div_result % 1 == 0 || div_result >= 100)
display = (int)div_result + measure;
// If result has 2 digits
else if (div_result >= 10) {
// Then fetch 1 decimal place as we have 2 digits
div_result = (Math.round(div_result * 10.0) / 10.0);
// If after rounding decimal places are .0 then truncate zeros
// eg. 99.97 rounded to -> 100.0 -> 100
if(div_result % 1 == 0)
display = (int)div_result + measure;
else
display = div_result + measure;
}
else
display = div_result + measure;
return display;
}
This can be done with much less effort using the DecimalFormat class. Let it do the rounding for you, which can be described in a pattern and choose the way of rounding by RoundingMode. It also takes care of the trailing zeros, which will be simply ignored.
public String pretty(int num) {
DecimalFormat f = new DecimalFormat("###.##");
f.setRoundingMode(RoundingMode.HALF_UP);
double prettyd = num;
int count = 0;
while (prettyd >= 1000.0) {
prettyd /= 1000.0;
count++;
}
return f.format(prettyd) + getUnit(count);
}

Manually convert float point number into binary format

Hi I have following float point value in base 10: 0.625. I need to convert this value in base 10 to binary format which is: 0.101.
Algorithm I found is below. It works, but I am not understanding why this works. Could someone please explain to be why the code below works? I am aware that numbers after the decimal point is computed in the manner such that 1/2^n where n is count from the decimal point. Thanks.
To clarify, I need to know the reasoning behind the mathematical formula. Not stepping through the code.
private static String floatToBinaryString( double n ) {
String val = "0.";
while ( n > 0 ) {
double r = n * 2;
if( r >= 1 ) {
val += "1";
n = r - 1;
}else{
val += "0";
n = r;
}
}
return val;
}
You multiply the fraction by 2 and use the ones place digit as the binary values until the fraction is equal to zero. Example below.
This is the standard formula for conversion using the 0.625 you have:
1) Multiply fraction by 2 => 0.625 * 2 = 1.25
The digit to the left of the decimal point is the first binary value, 0.1 so far
2) Ignore the ones-place digit and you have 0.25 which is still larger than zero.
Multiply the fraction by 2 => 0.25 * 2 = 0.50
The digit to the left of the decimal point is the next binary value, 0.10 so far
3) Ignore the ones-place digit and you have 0.50 which is less than zero.
Multiply the fraction by 2 => 0.5 * 2 = 1.00
The digit to the left of the decimal point is the next binary value, 0.101 so far
4) Ignore the ones-place digit and you have 0.00 which is equal to zero.
Conversion complete!
private static String floatToBinaryString( double n ) {
String val = "0."; // Setting up string for result
while ( n > 0 ) { // While the fraction is greater than zero (not equal or less than zero)
double r = n * 2; // Multiply current fraction (n) by 2
if( r >= 1 ) { // If the ones-place digit >= 1
val += "1"; // Concat a "1" to the end of the result string (val)
n = r - 1; // Remove the 1 from the current fraction (n)
}else{ // If the ones-place digit == 0
val += "0"; // Concat a "0" to the end of the result string (val)
n = r; // Set the current fraction (n) to the new fraction
}
}
return val; // return the string result with all appended binary values
}

How to round integer in java

I want to round the number 1732 to the nearest ten, hundred and thousand. I tried with Math round functions, but it was written only for float and double. How to do this for Integer? Is there any function in java?
What rounding mechanism do you want to use? Here's a primitive approach, for positive numbers:
int roundedNumber = (number + 500) / 1000 * 1000;
This will bring something like 1499 to 1000 and 1500 to 2000.
If you could have negative numbers:
int offset = (number >= 0) ? 500 : -500;
int roundedNumber = (number + offset) / 1000 * 1000;
(int)(Math.round( 1732 / 10.0) * 10)
Math.round(double) takes the double and then rounds up as an nearest integer. So, 1732 will become 173.2 (input parameter) on processing by Math.round(1732 / 10.0). So the method rounds it like 173.0. Then multiplying it with 10 (Math.round( 1732 / 10.0) * 10) gives the rounded down answer, which is 173.0 will then be casted to int.
Use Precision (Apache Commons Math 3.1.1)
Precision.round(double, scale); // return double
Precision.round(float, scale); // return float
Use MathUtils (Apache Commons Math) - Older versions
MathUtils.round(double, scale); // return double
MathUtils.round(float, scale); // return float
scale - The number of digits to the right of the decimal point. (+/-)
Discarded because method round(float,
scale) be used.
Math.round(MathUtils.round(1732, -1)); // nearest ten, 1730
Math.round(MathUtils.round(1732, -2)); // nearest hundred, 1700
Math.round(MathUtils.round(1732, -3)); // nearest thousand, 2000
Better solution
int i = 1732;
MathUtils.round((double) i, -1); // nearest ten, 1730.0
MathUtils.round((double) i, -2); // nearest hundred, 1700.0
MathUtils.round((double) i, -3); // nearest thousand, 2000.0
You could try:
int y = 1732;
int x = y - y % 10;
The result will be 1730.
Edit: This doesn't answer the question. It simply removes part of the number but doesn't "round to the nearest".
At nearest ten:
int i = 1986;
int result;
result = i%10 > 5 ? ((i/10)*10)+10 : (i/10)*10;
(Add zero's at will for hundred and thousand).
why not just check the unit digit...
1. if it is less than or equal to 5, add 0 at the unit position and leave the number as it is.
2. if it is more than 5, increment the tens digit, add 0 at the unit position.
ex: 1736 (since 6 >=5) the rounded number will be 1740.
now for 1432 (since 2 <5 ) the rounded number will be 1430....
I hope this will work... if not than let me know about those cases...
Happy Programming,
very simple. try this
int y = 173256457;int x = (y/10)*10;
Now in this you can replace 10 by 100,1000 and so on....
Its very easy..
int x = 1234;
int y = x - x % 10; //It will give 1230
int y = x - x % 100; //It will give 1200
int y = x - x % 1000; //It will give 1000
The above logic will just convert the last digits to 0. If you want actual round of//
For eg. 1278 this should round off to 1280 because last digit 8 > 5 for this i wrote a function check it out.
private double returnAfterRoundDigitNum(double paramNumber, int noOfDigit)
{
double tempSubtractNum = paramNumber%(10*noOfDigit);
double tempResultNum = (paramNumber - tempSubtractNum);
if(tempSubtractNum >= (5*noOfDigit))
{
tempResultNum = tempResultNum + (10*noOfDigit);
}
return tempResultNum;
}
Here pass 2 parameters one is the number and the other is position till which you have to round off.
Regards,
Abhinav
I usually do it this way:
int num = 1732;
int roundedNum = Math.round((num + 9)/10 * 10);
This will give you 1740 as the result.
Hope this will help.
int val2 = 1732;
val2 = (int)(Math.rint((double) i / 10) * 10);
The output is:1730
Have you looked at the implementation of Mathutils.round() ? It's all based on BigDecimal and string conversions. Hard to imagine many approaches that are less efficient.
Without using any math utils, rounding could be achieved to any unit as below:
double roundValue (double input, double toNearest){
//toNearest is any rounding base like 10, 100 or 1000.
double modValue = input % toNearest;
System.out.println(modValue);
if(modValue == 0d){
roundedValue = input;
}
else
{
roundedValue = ((input - modValue) + toNearest);
}
System.out.println(roundedValue);
return roundedValue;
}

Categories