How does Automatic conversion works in java? - java

So i had this exercise to add first seven terms from 1 to 7 in order like 1/1!+2/2!+3/3!........7/7!. Below is my code:
public class Problem9
{
public static void main(String args[])
{
int num, i;
float result = 1.0f;
for(num=2; num<=4; num++)
{
i =num;
int fact_num=1;
while(i>=1)
{
fact_num = i*fact_num;
i--;
}
System.out.println("num = "+num);
System.out.println("fact = "+fact_num);
result = result+ (float)num/fact_num;// This line is the one i m
// talking about
}
System.out.printf("The result = %.3f ",result);
}
}
So what is the difference between following line
result = result+ (float)num/fact_num;
and
result = result+ (float)(num/fact_num);
How is the conversion working here.

(float)(num/fact_num) performs int division and casts the result to float, which means that if num < fact_num, the result would be 0.0.
(float)num/fact_num casts num to float and performs floating point division, which means the result won't be 0.0 if num < fact_num (unless num is 0 of course). This is the form you should use in your code, since you are performing divisions whose results are smaller than 1, so int division won't give you the correct result.

(float)(num/fact_num);
Means the result of the two integer divisions casts into a float. The final answer will be a float.
(float)num/fact_num;
Here the int num is cast into a float. the divided by an integer.
For example :
int num = 5;
int fact_num = 2;
System.out.println((float)(num/fact_num));
will give an output of:
2.0

Related

Method works but throws errors for particular numbers

I wrote a method that calculates the combination of 2 numbers and it works for smaller numbers where n = 10 and r = 3, but when input n as 100 and r as 3 it throws an arithmetic exception
" / by zero"
import java.util.Scanner;
public class Combination {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("Enter n: ");
int n = scan.nextInt();
System.out.print("\nEnter r: ");
int r = scan.nextInt();
scan.close();
int ans = factorial(n) / (factorial((n-r)) * factorial(r));
System.out.print("\nThe combination is: "+ans);
}
static int factorial(int num) {
for(int i = num; i>1; --i) {
num *= (i - 1);
}
return num;
}
}
but i don't know what the problem is. it works for smaller numbers of n.
You're multiplying values which result in a number too big to fit inside an integer.
If you print out the num inside your for loop, you'll notice it eventually either goes negative or to zero. This is due to overflow.
For your example of n=100 and r=3 not even long will do. You'll need to use something like BigInteger.
Keep in mind that using BigInteger will drastically slow down your program when compared to using primitives.
If you're not interested in having such large numbers and were just curious why it wasn't working, you can also use Math.multiplyExact(int x, int y) or Math.multiplyExact(long x, long y) if you're using Java 8 or above.
By using these methods, you'll avoid having to deal with the side-effects of overflow since they will throw an ArithmeticException if the result overflows.
Change the data type of num from int to double

Get a numer decimal part as Integer using only math

Edit: This has to do with how computers handle floating point operations, a fact that every programmer faces once in a lifetime. I didn't understand this correctly when I asked the question.
I know the simplest way to start dealing with this would be:
val floatNumber: Float = 123.456f
val decimalPart = floatNumber - floatNumber.toInt() //This would be 0.456 (I don't care about precision as this is not the main objective of my question)
Now in a real world with a pen and a piece of paper, if I want to "convert" the decimal part 0.456 to integer, I just need to multiply 0.456 * 1000, and I get the desired result, which is 456 (an integer number).
Many proposed solutions suggest splitting the number as string and extracting the decimal part this way, but I need the solution to be obtained mathematically, not using strings.
Given a number, with an unknown number of decimals (convert to string and counting chars after . or , is not acceptable), I need to "extract" it's decimal part as an integer using only math.
Read questions like this with no luck:
How to get the decimal part of a float?
How to extract fractional digits of double/BigDecimal
If someone knows a kotlin language solution, it would be great. I will post this question also on the math platform just in case.
How do I get whole and fractional parts from double in JSP/Java?
Update:
Is there a "mathematical" way to "calculate" how many decimals a number has? (It is obvious when you convert to string and count the chars, but I need to avoid using strings) It would be great cause calculating: decimal (0.456) * 10 * number of decimals(3) will produce the desired result.
Update 2
This is not my use-case, but I guess it will clarify the idea:
Suppose you want to calculate a constant(such as PI), and want to return an integer with at most 50 digits of the decimal part of the constant. The constant doesn't have to be necessarily infinite (can be for example 0.5, in which case "5" will be returned)
I would just multiply the fractional number by 10 (or move the decimal point to the right) until it has no fractional part left:
public static long fractionalDigitsLong(BigDecimal value) {
BigDecimal fractional = value.remainder(BigDecimal.ONE);
long digits;
do {
fractional = fractional.movePointRight(1); // or multiply(BigDecimal.TEN)
digits = fractional.longValue();
} while (fractional.compareTo(BigDecimal.valueOf(digits)) != 0);
return digits;
}
Note 1: using BigDecimal to avoid floating point precision problems
Note 2: using compareTo since equals also compares the scale ("0.0" not equals "0.00")
(sure the BigDecimal already knows the size of the fractional part, just the value returned by scale())
Complement:
If using BigDecimal the whole problem can be compressed to:
public static BigInteger fractionalDigits(BigDecimal value) {
return value.remainder(BigDecimal.ONE).stripTrailingZeros().unscaledValue();
}
stripping zeros can be suppressed if desired
I am not sure if it counts against you on this specific problem if you use some String converters with a method(). That is one way to get the proper answer. I know that you stated you couldn't use String, but would you be able to use Strings within a Custom made method? That could get you the answer that you need with precision. Here is the class that could help us convert the number:
class NumConvert{
String theNum;
public NumConvert(String theNum) {
this.theNum = theNum;
}
public int convert() {
String a = String.valueOf(theNum);
String[] b = a.split("\\.");
String b2 = b[1];
int zeros = b2.length();
String num = "1";
for(int x = 0; x < zeros; x++) {
num += "0";
}
float c = Float.parseFloat(theNum);
int multiply = Integer.parseInt(num);
float answer = c - (int)c;
int integerForm = (int)(answer * multiply);
return integerForm;
}
}
Then within your main class:
public class ChapterOneBasics {
public static void main(String[] args) throws java.io.IOException{
NumConvert n = new NumConvert("123.456");
NumConvert q = new NumConvert("123.45600128");
System.out.println(q.convert());
System.out.println(n.convert());
}
}
output:
45600128
456
Float or Double are imprecise, just an approximation - without precision. Hence 12.345 is somewhere between 12.3449... and 12.3450... .
This means that 12.340 cannot be distinghuished from 12.34. The "decimal part" would be 34 divided by 100.
Also 12.01 would have a "decimal part" 1 divided by 100, and too 12.1 would have 1 divided by 10.
So a complete algorith would be (using java):
int[] decimalsAndDivider(double x) {
int decimalPart = 0;
int divider = 1;
final double EPS = 0.001;
for (;;) {
double error = x - (int)x;
if (-EPS < error && error < EPS) {
break;
}
x *= 10;
decimalPart = 10 * decimalPart + ((int)(x + EPS) % 10);
divider *= 10;
}
return new int[] { decimalPart, divider };
}
I posted the below solution yesterday after testing it for a while, and later found that it does not always work due to problems regarding precision of floats, doubles and bigdecimals. My conclusion is that this problem is unsolvable if you want infinite precision:
So I re-post the code just for reference:
fun getDecimalCounter(d: Double): Int {
var temp = d
var tempInt = Math.floor(d)
var counter = 0
while ((temp - tempInt) > 0.0 ) {
temp *= 10
tempInt = Math.floor(temp)
counter++
}
return counter
}
fun main(args: Array <String> ) {
var d = 3.14159
if (d < 0) d = -d
val decimalCounter = getDecimalCounter(d)
val decimalPart = (d - Math.floor(d))
var decimalPartInt = Math.round(decimalPart * 10.0.pow(decimalCounter))
while (decimalPartInt % 10 == 0L) {
decimalPartInt /= 10
}
println(decimalPartInt)
}
I dropped floats because of lesser precision and used doubles.
The final rounding is also necessary due to precision.

Decimal point control

I doing a program that will print out the sum and average of a set of numbers. I'm pretty new to java, and I can't seem to figure out how to get the .7 that is supposed to be on the end of the average, I only get .0. I don't think it has to do with my math, I think there is an error in my rounding statement. Could someone point the error out to me? Thanks guys.
public class Program
{
public static void main (String[]args)
{
int a = 475;
int b = 821;
int c = 369;
int d = 562;
int e = a+b+c+d;
double f = e/4;
f=(int)(f*10+.5)/10;
System.out.println("The sum of the four numbers is "+ e + " and the average is "+ f);
}
}
Instead of double f = e/4;, do double f = e/4.0;
With e/4, you divide an int by an int, which results in an int. The result is afterwards assigned to a double. That's why you don't get decimals in your result.
With e/4.0, you divide an int by a double, which results in a double.
You lost the decimal point because e/4 is an integer. try e/4F to indicate the expression as float number
double f = e/4F;
When you have an integer divide by another integer, this is call integer division. The output will the discard the decimal values.
For example:
double v1 = 5/2; //Value of v1: 2.0 (0.5 discarded)
double v2 = 10/3; //Value of v2: 3.0 (0.333 discarded)
An integer division is happening in your codes at this line:
double f = e/4;
Hence, all the decimal values are discarded.
To retain the decimal value, you can simply do one the following (to indicate one of the operand is a decimal value, hence integer division will not occur):
double f = e/4.0;
double f = e/(double)4;
double f = e/4d;

Java Comp Sci nested loops to find closest fraction

I want to find the closest fraction equal to 16/76. Whenever i run this i get 1 no matter what. I am doing this for Java class in school.
public class ClassOne {
public static double limit = 16/76;
public static double difference = 1;
public static double numer = 1;
public static double denom = 1;
public static void main(String[] args)
{
for(int i = 1;i<=100;i++)
{
for(int x = 1;x<=100;x++)
{
double temp = limit-(double)(x/i);
System.out.println((x/i));
if(Math.abs(temp) < difference && x/i != 16/76){difference = temp;numer = x; denom = i;
System.out.println("hi");}
}
}
System.out.println(numer + " " + denom);
}
}
A few problems
Use (double)x/(double)i where needed - probably assign to a temp
difference=temp should be difference=Math.abs(temp) or put the abs on the original temp computation
x/i = 16/76 is subject to floating point errors and so may not be hit when you want. May want to use something like 16*i != 76*x which can be computed in integers. I get 21 100.
You're encountering integer division here:
limit - (double)(x/i)
...and here:
public static double limit = 16/76;
Both x and i are int. The cast here will take effect after the division operation has taken effect.
Change your cast so that it applies immediately to one of the variables instead:
limit - ((double)x)/i
Also, consider wherever else you're doing any quotient that isn't with a floating point number (i.e. has a decimal after it or is explicitly cast to a double) - if you need it to be a floating point number, then use the appropriate cast.

Check if a number is a double or an int

I am trying to beautify a program by displaying 1.2 if it is 1.2 and 1 if it is 1 problem is I have stored the numbers into the arraylist as doubles. How can I check if a Number is a double or int?
Well, you can use:
if (x == Math.floor(x))
or even:
if (x == (long) x) // Performs truncation in the conversion
If the condition is true, i.e. the body of the if statement executes, then the value is an integer. Otherwise, it's not.
Note that this will view 1.00000000001 as still a double - if these are values which have been computed (and so may just be "very close" to integer values) you may want to add some tolerance. Also note that this will start failing for very large integers, as they can't be exactly represented in double anyway - you may want to consider using BigDecimal instead if you're dealing with a very wide range.
EDIT: There are better ways of approaching this - using DecimalFormat you should be able to get it to only optionally produce the decimal point. For example:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
DecimalFormat df = new DecimalFormat("0.###");
double[] values = { 1.0, 3.5, 123.4567, 10.0 };
for (double value : values)
{
System.out.println(df.format(value));
}
}
}
Output:
1
3.5
123.457
10
Another simple & intuitive solution using the modulus operator (%)
if (x % 1 == 0) // true: it's an integer, false: it's not an integer
I am C# programmer so I tested this in .Net. This should work in Java too (other than the lines that use the Console class to display the output.
class Program
{
static void Main(string[] args)
{
double[] values = { 1.0, 3.5, 123.4567, 10.0, 1.0000000003 };
int num = 0;
for (int i = 0; i < values.Length; i++ )
{
num = (int) values[i];
// compare the difference against a very small number to handle
// issues due floating point processor
if (Math.Abs(values[i] - (double) num) < 0.00000000001)
{
Console.WriteLine(num);
}
else // print as double
{
Console.WriteLine(values[i]);
}
}
Console.Read();
}
}
Alternatively one can use this method too, I found it helpful.
double a = 1.99;
System.out.println(Math.floor(a) == Math.ceil(a));
You can use:
double x=4;
//To check if it is an integer.
return (int)x == x;

Categories