printing wrong decimal - java

arr[i]=s+t-Math.abs(s-j)/2;
here is the line, s= 600 j = 631 t =60 , the answer should be 645.5 but it prints 645.0.
arr[] is double

Assuming that the types of s and j are int, you must be performing Java's integer division, which results in an int. s-j results in -31, and the Math.abs overload that takes an int is called, and 31 is returned. Integer division in Java means that 31/2 is 15 the int, not 15.5 the double.
Use the floating-point literal 2.0 to force floating-point division (or cast one of the / operands to a double):
arr[i]=s+t-Math.abs(s-j)/2.0;

Its because you are losing precision while dividing ints .Put a cast around the division
arr[i]= s+ t- (double) Math.abs(s-j)/2;

Try putting.
arr[i]=s+t-Math.abs(s-j)/2.0;
The trick here is that when you do divide by 2 it will give you an integer answer. So for your case( Math.abs(-31)/2 -> 15 instead of 15.5. and thus will truncate the .5
Therefore, by adding the 2.0 it will give you a double answer that is 15.5 and give you the desired solution

Probably s-j is an integer-valued (or long-valued) expression in your example, which makes Java select an integer/long valued Math.abs(...) call, returning an integer/long value. When dividing integer values, the decimal places are truncated. For example, 3 / 2 becomes 1, 15 / 2 becomes 7.
An easy way to make the expression evaluated with floating point math, is to divide by 2.0 instead:
arr[i] = s + t - Math.abs(s-j) / 2.0;
These other writing styles will work too:
arr[i] = s + t - Math.abs(s-j) / 2.;
arr[i] = s + t - Math.abs(s-j) / 2f;
arr[i] = s + t - Math.abs(s-j) / 2d;

You should set 2f in order to make a decimal division (now you are doing a integer division in Math.abs(s-j)/2)
Then your code should be
arr[i] = s + t - Math.abs(s-j)/2f;

Related

Getting 0 when trying to calculate slope

Here is the specific equation that's giving me 0 when it should be giving me -0.4 (-2/5)
slope2 = ((yVals[i+2] - originY) / (xVals[i+2] - originX));
(-2 - 0) / (2 + 3)
slope2 is a double
yVals[] is an int array
origin is an int
Why does it keep returning 0? I know the variables are being called correctly because I've done a println on the different vals and they are correct.
You are performing integer division in Java, where math done using ints must yield an int, so the division truncates anything beyond the decimal point. This means that in Java, -2 / 5 is 0. It's not enough that the target of the assignment is a double. One of the operands must be double (or float) to force floating-point arithmetic.
Cast one of the operands to the / operator to a double to force floating-point arithmetic.
slope2 = ( (double) (yVals[i+2] - originY) / (xVals[i+2] - originX));

Get the next higher integer value in java [duplicate]

This question already has answers here:
How to round up the result of integer division?
(18 answers)
How to round up integer division and have int result in Java? [duplicate]
(9 answers)
Closed 4 years ago.
I know I can use Math.java functions to get the floor, ceil or round value for a double or float, but my question is -- Is it possible to always get the higher integer value if a decimal point comes in my value
For example
int chunkSize = 91 / 8 ;
which will be equal to 11.375
If I apply floor, ceil or round to this number it will return 11 I want 12.
Simply If I have 11.xxx I need to get 12 , if I have 50.xxx I want 51
Sorry The chunkSize should be int
How can I achieve this?
Math.ceil() will do the work.
But, your assumption that 91 / 8 is 11.375 is wrong.
In java, integer division returns the integer value of the division (11 in your case).
In order to get the float value, you need to cast (or add .0) to one of the arguments:
float chunkSize = 91 / 8.0 ;
Math.ceil(chunkSize); // will return 12!
ceil is supposed to do just that. I quote:
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.
EDIT: (thanks to Peter Lawrey): taking another look at your code you have another problem. You store the result of integer division in a float variable: float chunkSize = 91 / 8 ; java looks at the arguments of the division and as they are both integers it performs integer division thus the result is again an integer (the result of the division rounded down). Now even if you assign this to the float chunkSize it will still be an integer(missing the double part) and ceil, round and floor will all return the same value. To avoid that add a .0 to 91: float chunkSize = 91.0 / 8;. This makes one of the arguments double precision and thus double division will be performed, returning a double result.
If you want to do integer division rounding up you can do
x / y rounded up, assuming x and y are positive
long div = (x + y - 1) / y;
In your case
(91 + 8 - 1) / 8 = 98 / 8 = 12
This works because you want to round up (add one) for every value except an exact multiple (which is why you add y - 1)
Firstly, when you write float chunkSize = 91 / 8 ; it will print 11.0 instead of 11.375
because both 91 and 8 are int type values. For the result to be decimal value, either dividend or divisor
or both have to be decimal value type. So, float chunkSize = 91.0 / 8; will result 11.375 and
now you can apply Math.ceil() to get the upper value. Math.ceil(chunkSize); will result in 12.0

Java Math.sin() doesn't work as expected

Okay, my assignment is to produce an array values a sine wave with a custom frequency.
This is my sine function:
Math.sin(frequency*(j/samplesPerSecond)*Math.PI*2)
j is the array index and samplesPerSecond equals 44100.
Now for an array of 100,000 values it returns 0.0 for the first 33,000, 1.571509...E-14 for the next 33,000 and 3.143018...E-14 for the rest.
I've tried System.out.println(Math.sin(Math.PI)); and it doesn't return 0 but it returns 1.224646...E-16
This is my first java assignment so I might be overlooking something really obvious here, but I'm really confused.
Try changing to this:
Math.sin(1.0 * frequency*(1.0 * j / samplesPerSecond) * Math.PI * 2)
See if it works better.
I suspect you have issue with integer division.
In Java 2/5 = 0, you know, while 1.0 * 2 / 5
is what you would expect usually ( 0.4 ).
Most probably you are dealing with integer division. So if the numerator is less than denominator it will round to zero. Try converting/casting j or samplesPerSecond to float or double.
j is the array index and samplesPerSecond equals 44100.
As an array index, I assume j is of type int. This is your primary issue, as you're performing integer division, which truncates the result to a whole number. Either cast j to a double, or multiply it by a double before dividing:
((double)j / samplesPerSecond)
(1.0 * j / samplesPerSecond)
I've tried System.out.println(Math.sin(Math.PI)); and it doesn't return 0 but it returns 1.224646...E-16
It has been already stated that this has to do with the finite precision of double.
I use something like this in those cases:
double result = Math.sin(2*Math.PI);
for(double d=-1;d<=1;d=d+0.05){
if(Math.abs(i-result) <1E-10){
result = d;
}
}
System.out.println(result); //prints 0

Explain "accumulated round-off error" for double values

I'm a self-taught beginner in java and having trouble understanding ints and doubles when used in the same equation
For example,
int x;
double x;
i = 5;
x = i / 2 + 1.0; // (answer 3.0)
z = (int) 1.0 + i / 2.0; // (answer 3.5)
What is with the rounding?
The problem is that this operation:
i / 2
... is performing an integer division. That's why 5 / 2 gives as result 2, not 2.5. This is normal behavior in Java, to perform a floating-point division you must make sure that at least one of the operands is a floating-point literal:
5 / 2.0
Now the above will return 2.5, as expected. Alternatively, you can cast either one of the operands:
((double) i) / 2
A division involving two ints will yield an int (thus, 5 / 2 = 2). If you use a double in one of the operands, it will yield a double (thus 5 / 2.0 = 2.5). The rest is operation precedence.
i / 2 = int 2 because both operands are integers and so integer division operation is used (yielding integer result)
i / 2.0 = double 2.5 because i is first coerced to double (type of the other operand) and double division is used
This is a case between integer and decimal division.
When two integers are divided, integer division is performed, that is, where the numbers are divided and the decimal component truncated.
When any number of the two numbers in question is a decimal (double/float) every other number gets treated as a decimal such that given the expression 5 / 2.0. The result will be 2.5 returned in whatever type of object 2.0 was (double by default).
Given a mixed equation such as 5 / 2 + 1.0, operator precedence defines how the expression should be evaluated. Since division has a higher precedence than addition, 5 / 2 gets evaluated as a integer division, returning 2 as an integer.
This is then added to 1.0 where the 2 gets promoted to a double before evaluation, returning the number 3.0 as a double as the final result.

Comparing float and double primitives in Java

I came across a strange corner of Java.(It seems strange to me)
double dd = 3.5;
float ff = 3.5f;
System.out.println(dd==ff);
o/p: true
double dd = 3.2;
float ff = 3.2f;
System.out.println(dd==ff);
o/p: false
I observed that if we compare any two values (a float and a double as I mentioned in the example) with .5 OR .0 like 3.5, 234.5, 645.0
then output is true i.e. two values are equal otherwise output is false though they are equals.
Even I tried to make method strictfp but no luck.
Am I missing out on something.
Take a look at What every computer scientist should know about floating point numbers.
Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation....
--- Edit to show what the above quote means ---
You shouldn't ever compare floats or doubles for equality; because, you can't really guarantee that the number you assign to the float or double is exact.
So
float x = 3.2f;
doesn't result in a float with a value of 3.2. It results in a float with a value of 3.2 plus or minus some very small error. Say 3.19999999997f. Now it should be obvious why the comparison won't work.
To compare floats for equality sanely, you need to check if the value is "close enough" to the same value, like so
float error = 0.000001 * second;
if ((first >= second - error) || (first <= second + error)) {
// close enough that we'll consider the two equal
...
}
The difference is that 3.5 can be represented exactly in both float and double - whereas 3.2 can't be represented exactly in either type... and the two closest approximations are different.
Imagine we had two fixed-precision decimal types, one of which stored 4 significant digits and one of which stored 8 significant digits, and we asked each of them to store the number closest to "a third" (however we might do that). Then one would have the value 0.3333 and one would have the value 0.33333333.
An equality comparison between float and double first converts the float to a double and then compares the two - which would be equivalent to converting 0.3333 in our "small decimal" type to 0.33330000. It would then compare 0.33330000 and 0.33333333 for equality, and give a result of false.
floating point is a binary format and it can represent numbers as a sum of powers of 2. e.g. 3.5 is 2 + 1 + 1/2.
float 3.2f as an approximation of 3.2 is
2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/4194304 + a small error
However double 3.2d as an approximation of 3.2 is
2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/8388608+ 1/16777216+ 1/134217728+ 1/268435456+ 1/2147483648+ 1/4294967296+ 1/34359738368+ 1/68719476736+ 1/549755813888+ 1/1099511627776+ 1/8796093022208+ 1/17592186044416+ 1/140737488355328+ 1/281474976710656+ 1/1125899906842624 + a smaller error
When you use floating point, you need to use appropriate rounding. If you use BigDecimal instead (and many people do) it has rounding built in.
double dd = 3.2;
float ff = 3.2f;
// compare the difference with the accuracy of float.
System.out.println(Math.abs(dd - ff) < 1e-7 * Math.abs(ff));
BTW the code I used to print the fractions for double.
double f = 3.2d;
double f2 = f - 3;
System.out.print("2+ 1");
for (long i = 2; i < 1L << 54; i <<= 1) {
f2 *= 2;
if (f2 >= 1) {
System.out.print("+ 1/" + i);
f2 -= 1;
}
}
System.out.println();
The common implementation of floating point numbers, IEEE754, allows for the precise representation of only those numbers which have a short, finite binary expansion, i.e. which are a sum of finitely many (nearby) powers of two. All other numbers cannot be precisely represented.
Since float and double have different sizes, the representation in both types for a non-representable value are different, and thus they compare as unequal.
(The length of the binary string is the size of the mantissa, so that's 24 for float, 53 for double and 64 for the 80-bit extended-precision float (not in Java). The scale is determined by the exponent.)
This should work:
BigDecimal ddBD = new BigDecimal(""+dd);
BigDecimal ffBD = new BigDecimal(""+ff);
// test for equality
ddBO.equals(ffBD);
Always work with BigDecimal when you want to compare floats or doubles
and always use the BigDecimal constructor with the String parameter!

Categories

Resources