Android Studio 0.5.2
Hello,
I have a random float value that I want to convert to an int.
The float could have a random number between -9.4182062E-9 to 9.593071E-8.
I just want to get the positive int number so if the number is negative i.e. -5.5115866E-8 it should just return 5. I have used the Math.abs for this.
I have tried the following:
int accel = (int)Math.abs(randomAccel);
However, accel keeps giving me a zero no matter what value randomAccel is.
Many thanks for any suggestions,
Your negative number -5.485747E-5 finish by E-5 meaning that it is -0.0000548574
So the absolute value is 0.0000548574.
So Math.abs(-0.0000548574) is 0.0000548574
(int)0.0000548574 is 0
result is 0
Are your sure your code is responding 0 no matter the value of random? Check the number you are trying to convert.
You should unit test your code with your values.
Your random number range has very small a magnitude (negative exponents) - importantly it is less than +/-1. When float is cast to int, all fractional parts are truncated, thus every number in your range, after setting the sign to positive, will result in 0 if cast to int.
It seems like you want to ignore the exponent of your numbers. One way to do that would be:
int accel = Integer.parseInt(String.valueOf(randomAccel).replaceAll("-?(\\d+).*", "$1"));
int accel = (int)Math.abs(randomAccel);
This line performs 3 steps
Get the absolute value of randomAccel
Cast the value to an int (floating point numbers are truncated)
Assign the int value to accel
Now lets look what happens when the input is in the range [-9.4182062E-9,9.593071E-
8] (By the way -5.485747E-5 is not in this range.)
Input value -9.4E-9 = -0.0000000094
1. -9.4E-9 converted to 9.4E-9
2. 9.4E-9 cast to int, fractional part is removed. Value is 0
3. 0 is assigned to `accel`
If you just want to most significant digit, you could multiply by 10^8 and see if that value is greater than 0, if it is then trucate, else multiply by 10 then truncate:
int accel = 0;
r = Math.abs( randomAccel ) * 100000000;
if( r >= 10 ) {/* error out of range */}
else if( r > 0 ) accel = (int)r;
else
{
r *= 10;
accel = (int)r;
}
import static java.lang.Math.*;
Convert part:
double input =-5.485747E-5; //for example
double tmp = abs(input);
tmp *= pow(10, abs(floor(log10(tmp))));
int out = (int) tmp;
System.out.println(out);
output:
5
Related
In Java String Integer::toString(long i, int radix) returns representation of number i using given radix(base). Before it does conversion it is mapping number i to -i:
byte[] buf = new byte[65];
int charPos = 64;
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
i = i / radix;
}
buf[charPos] = (byte)Integer.digits[(int)(-i)];
I do not understand why it works with negative number instead of positive. In Java x % y = -((-x) % y) so it is confusing to me because it should not do any difference because result of modulo operation is negated in the code.
The code doesn't want to handle positive and negative values differently, so it wants to unify the sign.
The most obvious normalization would be to convert negative value to positive. That's what we humans would do. But, with numbers stored in two's compliment, the value range of negative numbers it one larger than the value range of positive numbers, so if we normalized to positive, it would fail for -2147483648, aka Integer.MIN_VALUE.
I wrote this little program to calculate pi.
While playing with the code and trying to find the most exact result, I found a point where my computer couldn't calalculate a result. It could do 33554430 repetitions within seconds, but if i increased the for loop to 33554431 it didn't output anything.
So is 33554430 a special number?
public class CalculatePi{
public static void main(String[] args){
float pi=0;
int sign=1;
for(float i=1; i <= 33554430; i+=2){
pi += (sign*(1.0/i));
sign*= -1;
}
pi *= 4;
System.out.println(pi);
}
}
You are getting and endless loop, because during the comparison i <= 33554431, the int value 33554431 is promoted to a float value which is "too precise" for float and will actually equal to 33554432.
Then, when you try to increase the value by +2, the float just isn't precise enough to increment from the value 33554432. To illustrate my point:
float f = 33554432;
System.out.println(f); //33554432
f += 2;
System.out.println(f); //33554432
So the value f doesn't increase due to its precision limitation. If you'd increase it by, say 11, you'd get 33554444 (and not 33554443) as that is the closest number expressible with that precision.
So is 33554430 a special number?
Sort of, not 33554430 but rather 33554432. First "special number" for float is 16777217, which is the first positive integer that cannot be represented as a float (equals 16777216 as float). So, if you'd increment your i variable by 1, this is the number you'd get stuck on. Now, since you are incrementing by 2, the number you get stuck on is 16777216 * 2 = 33554432.
public class CalculatePi{
public static void main(String[] args){
float pi=0;
int sign=1;
for(float i=1; i <= 33554431; i+=2){
pi += (sign*(1.0/i));
sign*= -1;
if( i > 33554410) System.out.println(i);
}
pi *= 4;
System.out.println(pi);
System.out.println((float)33554431);
System.out.println((float)33554432);
System.out.println((float)33554434);
}
}
You compare float with int in for loop. When you convert 33554431 (it's int value) to float you get 3.3554432E7.
It's about accuracy, precision. When you run:
System.out.println((float)33554431); // -> 3.3554432E7
System.out.println((float)33554432); // -> 3.3554432E7
System.out.println((float)33554434); // -> 3.3554432E7
All 3 prints 3.3554432E7, it means that when you increase float value of 33554432 by 2, you get 3.3554432E7, exactly this same value, and your loop runs forever.
Your loop increments by 2 each time.
2 * 33554430 = 67108860
2 ^ 26 = 67108864
Maybe Java stores floating point numbers in a 32bit system by using 26bits for the mantissa and 6 bits for the exponent?
This version works for both. It's the float loop variable causing problems:
public static void main(String[] args){
float pi=0;
int sign=1;
for(int i=1; i <= 33554430; i+=2){
pi += (sign*(1.0/(float)i));
sign*= -1;
}
pi *= 4;
System.out.println(pi);
}
Probably this is due this issue:
The finite nonzero values of any floating-point value set can all be
expressed in the form s · m · 2(e - N + 1), where s is +1 or -1, m is
a positive integer less than 2N, and e is an integer between Emin =
-(2K-1-2) and Emax = 2K-1-1, inclusive, and where N and K are parameters that depend on the value set.
I am not very familiar with how to alter the range of both Math.random or a new Random() to generate a double like this. I need to be able to generate a double between -10 and 25 cents (my program is dealing with money; hence why I said cents). And a separate instance is generating a random double between 90 and -75 cents. I saw this when I was searching for my answer:
double result = Math.random() * (upper - lower) + lower;
But when I implemented the idea into my code, the range didn't seem to work when using a range between a positive and a negative number...
I tested it with the upper limit of 0.25 and lower of -0.10, but noticed it printed 0.3567587946356543 at one instance of the test I did. So by this I concluded that I obviously didn't adjust the range correctly..
Please help :(
This is my first time using stackoverflow so please go easy on me, I will elaborate if anything I said didn't make sense..
This is my existing method using this code:
public double variation(double price){
//formula: (Math.random() * range) + min; where range = max - min
//80% of the time returns amount between -10 & 25 cents
if(Math.random() > 0.19){
return (Math.random() * 0.35) - 0.10;
}
//20% of the time returns amount between -75 & 90 cents
return (Math.random() * 1.65) - 0.75;
}
I know the method takes in a double price that it doesn't use; it's part of the teacher's requirements to take in a double price but to disregard its value. So ignore that please.
Now you have included all your code in the question, so my answer is changed to:
When it printed 0.3567587946356543 then it comes from the 20% part with range -.75 to 0.90 when the first Math.random() call in if(Math.random() > 0.19){ becomes false.
Old answer:
I think you forgot the minus at the lower value:
double upper = 0.25;
double lower = -0.10;
double result = Math.random() * (upper - lower) + lower;
To generate between -10 and 25, try doing :-
Random r = new Random();
int d = r.nextInt(35)+1;
d = d - 10;
double result = d/100.0;
or a one liner
double result = ((r.nextInt(35)+1)-10)/100.0;
Looks like your formula is actually correct:
double result = Math.random() * (upper - lower) + lower;
You can test it by putting the min and max possible random (which is zero, 1)
Random Value | Result
---------------------------
0 | -0.1 (lower)
1 | 0.25
0.5 | 0.075
0.01 | -0.0965
Working back to get the Random value for the result to be 0.356758795, the Math.random() must return 1.305025128 which is not gonna be the case. :)
Having said that, Apache Commons3 has this nifty method RandomUtils.nextDouble(double startInclusive, double endInclusive); that does it for you.
To get an output with a long decimal:
it's a little bit rough, but it gets the job done.
Random rand = new Random();// creates 'Random' method
int number = rand.nextInt(35)+1;// gets a random integer out of 35
double randDouble = rand.nextDouble();//gets a random double
double finalNumber = ((number + randDouble)-10)/100;//adds the integer and the double,
//subtracts ten, and divides by 100
System.out.println(finalNumber);// prints the number
Here are some examples of the output (copied and pasted exactly).
0.22748959958842008
0.1963085030978741
0.17300671109908058
-0.002656673961685705
-0.08854411636457332
0.03578255664449403
To get an output with a two digit output:
Random rand = new Random(); // creates 'Random' method
float x = rand.nextInt(35)+1; // gets a random integer(0 through 35)
float y = x - 10; // subtracts that number by ten(making the new range -10 through 25)
float z = y/100; // puts number in decimal form
NOTICE this line int number = rand.nextInt(35)+1(in the long decimal version). The reason you have to do +1 at the end is because Java understands 1 as 0. see chart below
JAVA |0 1 2 3 4 5
-------|-----------
HUMANS |1 2 3 4 5 6
I took 400.0 and - 400.0 for example.
double min = 400.0;
double max = 2 * min;
System.out.println(Math.random() * max - min);
And the output is
138.0921773815627
212.7567891431654
9.063135840057157
-256.8594518458244
-99.84573995806142
116.53331370219462
33.29613621235126
Im trying to find the result of 1/1 + 1/4 + 1/9 + 1/16 + 1/25 ...
These is the lines I wrote that give the result Infinity:
public class BaselProblem {
public static void main(String[] args) {
int testLimit = 100000;
double sum = 0;
for (int i = 1; i<testLimit; i++)
{
sum = sum + 1.0/(i*i);
}
System.out.println(sum);
}
}
Changing 1.0/(i*i) to 1/(1.0*i*i) gives the correct result 1.6449240667982423. Why is it that only the 2nd form work but not the 1st?
Also, because (i*i) > 1, then 1.0/(i*i) should be < 1, so how can it leads to in Infinity?
Because your testLimit as well as your i are defined as int. Since you put the expression i*i in parentheses, it will be calculated first, and will try to find the multiple of two integers - which will reach overflow pretty quickly and reset to zero.
Specifically, when i reaches 2¹⁶, i*i will be 2³². This means 1 followed by 32 zeros in binary, of which, only the 32 zeros are kept, which means zero. (Thanks #templatetypedef).
Therefore, you'll have a number divided by zero, which is infinity.
Change your loop declaration so that i is double. Or multiply by a double (1.0) on the left hand of i*i. This will cause the expression to be changed into double before multiplying by the second i.
Java integer have a maximum value of 2,147,483,647. You're eventually surpassing that maximum with the integer that results from i*i.
If you do 1.0*i*i, you're converting the result to a double which can hold a maximum value of 1.79769313486231570E+308.
Your maximum value for i*i will be 10,000,000 which a double can hold, but an integer can't.
how can i round up a floating point number to the next integer value in Java? Suppose
2.1 -->3
3.001 -->4
4.5 -->5
7.9 -->8
You should look at ceiling rounding up in java's math packages: Math.ceil
EDIT: Added the javadoc for Math.ceil. It may be worth reading all the method in Math.
http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#ceil%28double%29
public static double ceil(double a)
Returns the smallest (closest to negative infinity) double value that
is greater than or equal to the argument and is equal to a
mathematical integer. Special cases:
If the argument value is already equal to a mathematical integer, then the result is the same as the argument.
If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument.
If the argument value is less than zero but greater than -1.0, then the result is negative zero.
Note that the value of Math.ceil(x) is exactly the value of
-Math.floor(-x).
try this
float a = 4.5f;
int d = (int) Math.ceil(a);
System.out.println(d);
I had the same issue where I was still getting the smaller int value. It was the division, not the Math.ceil. You have to add a (float) cast to the ints. This is how I fixed it:
int totalNumberOfCachedData = 201;
int DataCountMax = 200;
float ceil =(float) totalNumberOfCachedData / (float)DataCountMax;
int roundInt = (int) Math.ceil(ceil);
This will give me 2 for the value of roundInt.
See
float a=10.34f,b=45.678f;
System.out.println((int)Math.ceil(a));
System.out.println((int)Math.ceil(b));
Output
11
46
If it helps someone, here's how I get this working:
int arraySize = 3;
int pageSize = 10;
int pagesQty = (int) Math.ceil(arraySize / (float) pageSize);
System.out.println(pagesQty);
//Displays 1
Divisor must be a float in order to work properly.
I'm using this:
public static int roundDoubleToUpperInt(double d){
return (d%1==0.0f)?(int)d:(int)(d+1);
}