Can 0.999... be rounded to 1 when multiplying? [duplicate] - java

This question already has answers here:
Can 0.99999999999 be rounded to 1.0 when multiplying?
(2 answers)
Closed 6 years ago.
When multiplying a floating point number that is very close to 1 with an int > 0, can it ever be interpreted as 1.
That is, if Math.random() returns its highest possible result (which is 1 step below 1.0), will
(int)(Math.random() * 8)
be 8 or 7?
For a practical example, can this often-used construct give an index out of bounds error:
someArray[(int)(Math.random() * someArray.length)];
I'm specifically interested in answers for Java and ActionScript 3, but I suppose they all use the same rules for floating point arithmetic, and answers for any platform would be useful.
Update: Though I already accepted an answer, I'd still appreciate confirmation that this can't go wrong in ActionScript 3 either, since a colleague reporting that he saw it go wrong once is what partly prompted me to ask this question.

Because 8 is a power of 2, multiplying a float by it will never add or remove precision from the value unless you overflow. Multiplying by other numbers, and in particular floating point numbers (other than a negative power of 2, e.g. 0.25, 0.0625, etc.), will reduce precision.

Using Math.random in java (http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html) the value can be greater than or equal to 0.0 and less than 1.0.
Using one test with value 0.999999 the value of (int)(Math.random() * 8) is 8. You can test the experiment using the next code
public static void main(String args[]) {
for (int i = 0; i <= 100; i++) {
double frac1=0.999999999999999999 ;
double frac=Math.random() ;
int integer=(int) (frac*8);
int integer1=(int) (frac1*8);
System.out.println( integer+"-"+frac);
System.out.println( integer1+"-"+frac);
}
}
But Math.random()*8 can return other values like 1,2,3,4,5,7 or 6 depends of the value returned for Math.random. You can test this running the sample code

Actually a quick exhaustive search can show that this cannot happen for any 32bit integer with floats:
public static void main(String[] args) {
int repr = Float.floatToIntBits(1f) - 1;
float val = Float.intBitsToFloat(repr);
for (long i = 1; i <= -(long)Integer.MIN_VALUE; i++) {
if ((int) (val * i) == i) {
System.out.println("FOUND VALUE: " + i);
}
if ((int) (val * -i) == -i) {
System.out.println("FOUND VALUE: " + -i);
}
if (i % 100000000 == 0) {
System.out.println("Done: " + (double)i/Integer.MAX_VALUE);
}
}
// nothing printed
}

Related

Why do we get 1 as remainder on the second println? [duplicate]

This question already has answers here:
How Does Modulus Divison Work
(19 answers)
Closed 5 years ago.
package PracticePackage;
public class whileLoop {
public static void main(String[] args) {
int i=1;
System.out.println("Quotient "+i/2);
System.out.println("Remainder "+i%2);
}
}
this is the fomula that Java uses to yield the remainder of its operands:
(a/b)*b+(a%b)
where a is the dividend and b is the divisor.
so in your case it's like:
int i = 1;
int b = 2;
int result = (i / b) * b + (i % b);
hence the result 1 rather than 0
1/2 = 0.5
you defined i as int
Integral division in java takes floor of the answer if the answer is a real number so 1/2 becomes 0, making 1%2 equal to 1
I hope that explains.
because integers are not real numbers so you get 1 as answer and the real part of remainder is ignored since you defined i as an integer

Java program to print exponential series for numbers 3 and 5 and limit the result to below 1000

I am new to Java programming and have tried a few problems on Project Euler. I somehow came up with my own problem of printing sequence of exponents of 3 and 5 and limit the result to below 1000. I have researched for 3 days to find the best approach to this problem but I could not find relevant articles. I have come across algorithms on exponential series but those were too advanced for my capability right now.
I would appreciate any help in solving this problem. Please see the code I have tried
public class Exponent {
public static void main (String[] args) {
// Declared integers for base and exponent
int i = 0; /* for base */
int n = 0; /* for exponent */
for (n=1; n<5; n++) {
for (i=1; i<=5; i++) {
if (i%3 == 0 || i%5 == 0) {
System.out.println(Math.pow(i,n));
}
}
}
}
}
This code prints out the following result:
3.0
5.0
9.0
25.0
27.0
125.0
81.0
625.0
My problem is that it is very apparent that I am forcing the exponent to print below 1000 by limiting the base and exponent value inside the loop
for (n=1; n<5; n++) //because n<=5 would print result for 5 power 5 which is 3125
I would like to somehow limit the result to below 1000 so not sure if this declaration is apt
int result = 1000; // result variable as 1000
Also, I want the code to print the output in alternates of 3 and 5 as shown below. My program prints the output in sequence of 3 and 5 respectively.
Desired output:
3.0
5.0
9.0
27.0
125.0
81.0
625.0
243.0
729.0
And stops there because the next value would exceed 1000.
I also wanted to know if there is any other approach instead of using Math.pow() method because it returns a double instead of an int. I would like to avoid the double value and just print as follows:
Without double:
3
5
9
27
81
125
243
625
729
Without using Math.pow() (and printing in different order ):
int[] bases = { 3, 5 };
long maxval = 1000L;
for (int base : bases) {
long value = base;
do {
System.out.println( value );
value *= base;
} while (value < maxval);
}
First create a double to store the result:
double result = 0;
Then create an infinite while loop which calculates the result using 3 and 5 and breaks out once result is above 1000.
while(true)
{
result = Math.pow(3, n);
if(result > 1000)
{
break;
}
System.out.println(((int)result));
result = Math.pow(5, n);
if(result < 1000)
{
System.out.println((int)result);
}
n++;
}
Since exponents of 3 are smaller than 5 don't break out until the maximum exponent in 3 is hit. Since the break does not occur don't print the 5 unless it is valid.
Also to print the double as an int value just cast it to an int.
EDIT:
If you are really worried about efficiency here is a faster solution:
public void calcExponents(int max)
{
int resultThree = 3;
int resultFive = 5;
while(resultThree < max)
{
System.out.println(resultThree);
if(resultFive < max)
{
System.out.println(resultFive);
}
resultThree *= 3;
resultFive *= 5;
}
}
You could also make the 3 and 5 arguments to take it one step further.
Why not check if the result is bigger than 1000, and just break out of the loop if it is?
if(Math.pow(i,n)>=1000)
break;
Hint:
3.0 = 3^1
5.0 = 5^1
9.0 = 3^2
25.0 = 5^2 // I assume you forgot it
27.0 = 3^3
125.0 = 5^3
81.0 = 3^4
625.0 = 5^4
243.0 = 3^5
729.0 = 3^6
and 3x is always smaller than 5x. So a single loop (for the x part) with two computations in the body of the loop one for 3 and one for 5 should do the job. You just have to use some condition for the less than 1000 part to avoid printing 55 and 56.
You could use a single loop, checking exponents for both 3 and 5 on each iteration, and printing each result that is less than 1000.
You just want to make sure that you break the loop once your 3's exceed 1000.
To print integer values, you can simply cast the result of Math.pow() to an int.
There are many different ways that one could write an algorithm like this. Here's a very simple (untested) example:
public class Exponent {
public static void main (String[] args) {
int i = 1; // or start at 0 if you prefer
// set the max value (could also be parsed from args)
int maxValue = 1000;
// the break condition also increments:
while (Math.pow(3, i++) < maxValue) {
int x3 = (int) Math.pow(3, i);
int x5 = (int) Math.pow(5, i);
if (x3 < maxValue) {
System.out.println(x3);
}
if (x5 < maxValue) {
System.out.println(x5);
}
}
}
}

Project Euler: #8 [duplicate]

This question already has answers here:
Why does Java think that the product of all numbers from 10 to 99 is 0?
(9 answers)
Closed 8 years ago.
When trying to answer this problem:
The four adjacent digits in the 1000-digit number that have the
greatest product are 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
Find the thirteen
adjacent digits in the 1000-digit number that have the greatest
product. What is the value of this product?
I get 2091059712 however Euler says the answer is incorrect is there anything I may be doing incorrectly?
public class LargestProductThirteen{
public static void main( String[] args ) {
final String num = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long greatestProduct = 0;
for (int i = 0; i < num.length() - 12; i++) {
long sum = Character.getNumericValue(num.charAt(i))*
Character.getNumericValue(num.charAt(i+1))*
Character.getNumericValue(num.charAt(i+2))*
Character.getNumericValue(num.charAt(i+3))*
Character.getNumericValue(num.charAt(i+4))*
Character.getNumericValue(num.charAt(i+5))*
Character.getNumericValue(num.charAt(i+6))*
Character.getNumericValue(num.charAt(i+7))*
Character.getNumericValue(num.charAt(i+8))*
Character.getNumericValue(num.charAt(i+9))*
Character.getNumericValue(num.charAt(i+10))*
Character.getNumericValue(num.charAt(i+11))*
Character.getNumericValue(num.charAt(i+12));
if (sum > greatestProduct)
greatestProduct = sum;
}
System.out.println(greatestProduct);
}
}
You are performing integer arithmetic when you are multiplying all those characters' numeric values together. With high digits, and 13 of them, it is likely that such a product would overflow an int, whose max value is about 2 billion (10 digits).
The Character.getNumericValue method returns an int. Cast the first return value as a long to force long math.
long sum = (long) Character.getNumericValue(num.charAt(i))*
Character.getNumericValue(num.charAt(i+1))*
...
Incidentally, even though you have greatestProduct already, for some reason you defined this variable as sum. Just for semantics' sake, I would name it product.
You are currently doing integer multiplication (e.g. multiplication of int(s)). Given your existing code - the easiest solution that I see is to change your sum calculation,
// This is a product, not a sum.
long sum = Long.valueOf(num.charAt(i))
* Long.valueOf(num.charAt(i + 1))
* Long.valueOf(num.charAt(i + 2))
* Long.valueOf(num.charAt(i + 3))
* Long.valueOf(num.charAt(i + 4))
* Long.valueOf(num.charAt(i + 5))
* Long.valueOf(num.charAt(i + 6))
* Long.valueOf(num.charAt(i + 7))
* Long.valueOf(num.charAt(i + 8))
* Long.valueOf(num.charAt(i + 9))
* Long.valueOf(num.charAt(i + 10))
* Long.valueOf(num.charAt(i + 11))
* Long.valueOf(num.charAt(i + 12));
That is a good puzzle.
Your code is failing because you are using Character.getNumericValue. You could use BigDecimal instead.
Hints
* Don't think that the whole number is a long String.
* You are looking for the max number, not the result.
* Adjacent goes in all directions.
* Don't try to use longs (or any other number containers). Regardless of the result, 9*9*7 is greater than 7*7*7. You don't have to multiply them to know that, so build a structure that finds the greatest between the inputs.
Building on Alexandre Santos comments, treat each 13 digit number as a string of 13 chars, you can sort the chars within the string, so 98031 becomes 01389, order of operands doesn't matter with multiplication (9*8*3 = 3*8*9). Now the problem is just finding the largest string ( compare strings with <). You only have to do the multiplication once, after you have found the largest string (by sort order not size.
Another implementation (using for instead of 13 similar things):
public static void main(String[] args) throws Exception {
String x = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int numberOfDigits = 13;
int dif = x.length() - numberOfDigits;
long max = 0;
for ( int i = 0 ; i <= dif ; i++ ) {
long p = 1;
int sup = i + numberOfDigits;
for ( int j = i ; j < sup ; j++ ) {
p*=Character.getNumericValue(x.charAt(j));
}
if ( p > max ) {
max = p;
}
}
System.out.println(max);
}
It can be improved using the following observation:
0 * ? = 0
simple example:
if ( x.charAt(i) == '0' ) {
continue;
}

Incorrect subtraction results: 3.999999, not 4 [duplicate]

This question already has answers here:
Adding and subtracting doubles are giving strange results [duplicate]
(2 answers)
Why do I see a double variable initialized to some value like 21.4 as 21.399999618530273?
(14 answers)
Closed 9 years ago.
So I narrowed down a bug in my application to java messing up a simple subtraction calculation. I can't figure out why exactly. Here is the bit of code:
for (double x = (((double)bdl.length())-1)/10; x > 0; x--) {
int count;
System.out.println("x = " + x);
if (x >= 1) {
System.out.println("X = " + x + " so count = 20");
count = (20);
} else {
count = (int)(x*20);
System.out.println("X = " + x + " so count = "+count);
}
}
The variable bdl is just a JSONArray, which I am only concerned with its length at this point. As bdl comes in initially it has length 15, so x will equal 1.4 . The first time through the loop the first println says "X = 1.4 so count = 20" which is correct. The second time through however when x should = 0.4, it instead says "X = 0.3999999999999999 so count = 7". I understand that casting (x*20) to an int at that point and time will give me 7, but my question is Why is x not equal to 0.4 .
You're using a double, which is a floating-point number. This is not meant for presision, moreover, it is meant for speed and non-precision. So instead, you should be using an int, like this:
for (int x = ((bdl.length())-1)/10; x > 0; x--) {
This will keep your numbers precise.
Actually, your 'x' does equal 0.4, it's only a matter of precision.
All floating point comparison operations should be executed with a certain precision (delta or epsilon in some implementations).
Refer to this post.

java for-loop problem

I am making a Java program to calculate Simpson's rule for integrals. Here is the code I have. Notice the second column of numbers in the output values of count == 4,9,10,11. They are not numbers that I need, they do not follow the pattern. I need these numbers to be accurate. What is going on and how can I fix it?
public static void main(String[] args)
{
double totalS = 0.0;
int count = 0;
for(double i=0; i< 4; i += 0.4 )
{
count++;
totalS += Sfunction(i, count);
System.out.println(count + " " + i + " " + totalS);
}
}
public static double Sfunction(double f1, int count)
{
double value;
if (f1 == 0.0 || f1 == 4.0)
value = Math.cos(Math.sqrt(f1));
else if ((count % 2) == 1)
value = 2 * Math.cos(Math.sqrt(f1));
else
value = 4 * Math.cos(Math.sqrt(f1));
return value;
}
I get the output of:
1 0.0 1.0
2 0.4 4.226313639540303
3 0.8 5.478244888601832
4 1.2000000000000002 7.30884788480188
5 1.6 7.911122809972827
6 2.0 8.534897589034324
7 2.4 8.578100205110182
8 2.8 8.168723348285942
9 3.1999999999999997 7.736055200662704
10 3.5999999999999996 6.452869366954546
11 3.9999999999999996 5.620575693860261
Each time you go round your loop, you are compounding the error in the inexact addition of 0.4 to i.
Instead, use an integral value for the loop counter, and scale that to get a better approximation to the values:
for ( int count = 0; count < 10; ++count ) {
final double i = 0.4 * count;
System.out.println ( ( count + 1 ) + " " + i );
}
This will not eliminate the floating point error, but it will mean it is not increasing at each iteration. To remove the error from the output, format the output to a reasonable number of decimal places:
for ( int count = 0; count < 10; ++count ) {
final double i = 0.4 * count;
System.out.printf ( "%2d %.1f\n", ( count + 1 ), i );
}
This is a classic floating point problem. If you need accuracy in your decimals, you should be using BigDecimal
This is how floating point numbers work in computers.
You can round the display, but the representation underneath won't change. Use java.text.DecimalNumberFormat to round to two decimal places.
What you are seeing is a result of floating point precision error, the numbers aren't stored like you're probably thinking. You can round the answer to 1 decimal place to get rid of the error...but this is just a result of how doubles are stored in java.
There's some good reading on this topic over here: Why do simple math operations on floating point return unexpected (inaccurate) results in VB.Net and Python?
Your problem is that you are using floating point arithmetic which can only approximate values, but assuming you have infinite precision. You shouldn't do equality tests like this with floating point numbers:
if (f1 == 0.0 || f1 == 4.0)
Any equality test with a floating point number is a code smell. With a float you should always check if it lies within a certain range, for example in the range 3.9999 to 4.0001.
In this specific example though, you also handily have another parameter called count which is an int. You can do equality tests with that. Maybe you can test that instead.
try to print them with only one decimal digit:
System.out.printf("%.1f", Math.E); // prints 2.7
System.out.printf("%.2f", Math.E); // prints 2.72
System.out.printf("%.3f", Math.E); // prints 2.718
or even try to specify the keyword strictfp for your number crunching methods
From your loop condition, it looks like you don't want line 11 to be processed at all. I recommend you use an integer loop index and use it to compute the values you pass to Sfunction. The following should be the equivalent of what you have now (except it leaves out line 11).
double totalS = 0.0;
for( int i = 1; i <= 10; i++ )
{
double f1 = 0.4 * (i - 1);
totalS += Sfunction(f1, i);
System.out.println(i + " " + f1 + " " + totalS);
}
Your problem with print precision can be solved with DecimalFormat, as suggested in other answers.

Categories