Matt
Matt

Reputation: 57

Rounding numbers when converting from Fahrenheit to Celsius (Java)?

I'm having an issue converting from Fahrenheit to Celsius in Java. I just started learning Java, and am still working my way through books and tutorials.

For my first program, I'm trying to create a basic temperature calculator based on this tutorial.

I'm wanting to extend it's functionality, and also include a Fahrenheit to Celsius conversion, as well as the base Celsius to Fahrenheit conversion.

So, I got the Celsius to Fahrenheit part working using the example code that was given, and now, using the same code, slightly modified after a lot of trial and error to get it to work, I'm trying to tackle the other half. I got it to work to some degree, but it's not completely correct.

When I enter, for example, 89 degrees Fahrenheit, it returns 31 Celsius instead of the expected 32. I'm thinking this is an issue in the way the number is getting rounded, but I'm not sure how to go about fixing it. I've done some reading, and I think it might be able to be fixed by setting the RoundingMode to "HALF_UP", but I'm not sure how to do it so that it affects only this conversion, and not the other one that works. This is what I have:

int tempCel = (int) ((int)((Double.parseDouble(tempTextFieldFC.getText())) 
         - 32) * .55555);
tempCelLabel.setText(tempCel + " ° Celsius"); 

Any help or suggestions that can be given will be greatly appreciated. Thanks for your time.

Upvotes: 3

Views: 4613

Answers (5)

Jernej Jerin
Jernej Jerin

Reputation: 3399

I know that OP is learning Java, but for the sake of other people that will come here looking for conversion from Fahrenheit to Celsius, I recommend using JScience library that has lots of features for developing scientific applications. One of that powerful features is also a unit conversion from NonSI units to SI units.

Here is a quick example for converting from Fahrenheit to Celsius:

Saving Fahrenheit value to String and parsing it to double. This two lines are the same as in @Jon Skeet answer.

String fahrenheitText = tempTextFieldFC.getText();
double fahrenheit = Double.parseDouble(fahrenheitText);

Now we build NonSI and SI unit. JScience includes base units, not multiplicative units like kilometer and centimeter. To create those units, SI provides methods to build composite units. Please see this references for more information. For detail explanation I recommend reading official API, which also has more examples.

Unit<Temperature> FAHRENHEIT = NonSI.FAHRENHEIT;
Unit<Temperature> CELSIUS = SI.CELSIUS;

Now we convert it to fahrenheit by asking the source unit for an appropriate converter to the destination unit and use the converter.

BigDecimal celsius = BigDecimal.valueOf(FAHRENHEIT.getConverterTo(CELSIUS).convert(fahrenheit));

For correct rounding I recommend using BigDecimal setScale() method. Now for RoundingMode I usually use HALF_UP, but that depends on situation. For Fahrenheit to Celsius conversion I recommend using HALF_UP rounding. We will set to round to one decimal digit.

celsius = celsius.setScale(1, RoundingMode.HALF_UP);

Setting value to label.

tempCelLabel.setText(celsius + "° Celsius");

Upvotes: 2

kjp
kjp

Reputation: 3116

tempCel should be declared float so that it can have fractional values. And then you should round tempCel when printing it

double tempCel = (Double.parseDouble("1.45")- 32) * .55555;
System.out.println(Math.round(tempCel));

Upvotes: 2

elias
elias

Reputation: 15490

Use this:

long tempCel = Math.round((5.0 / 9.0) * (Double.parseDouble(tempTextFieldFC.getText()) - 32 ));
tempCelLabel.setText(tempCel + " ° Celsius"); 

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500953

Use Math.round() to perform rounding, instead of casting to int. Casting always rounds towards 0, as per JLS section 5.1.3:

Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3).

Note that Math.round(double) is still declared to return a double, as it may be outside the range of int or long - but I would expect that not to be a problem in your case.

I'd also advise you to split up your code into multiple statements instead:

String fahrenheitText = tempTextFieldFC.getText();
double fahrenheit = Double.parseDouble(fahrenheitText);
double celsius = ((fahrenheit - 32) * 5) / 9;
int celsiusRounded = (int) Math.round(celsius);
tempCelLabel.setText(celsiusRounded + "° Celsius");

Upvotes: 5

musiphil
musiphil

Reputation: 3847

Break down your calculation:

double fahrenheit = Double.parseDouble(tempTextFieldFC.getText());
double celcius = (fahrenheit - 32) * 5 / 9;
tempCelLabel.setText(Math.round(celcius) + " ° Celsius");

and get rid of all those temp prefixes — they don't mean much.

Upvotes: 1

Related Questions