Truncating a number

How do I round a number? I am writing a program that converts an inputted temperature in Fahrenheit to celsius. The limitations were that the input has to be an integer, but the converted temperature has to have 1 decimal place.

So,here is a snippet of the code:

double degreesC;

//gets the user input in integer fahrenheit

degreesF = keyboard.nextInt();

//converts integer to double fahrenheit

double dblDegreesF = (double)degreesF;

//calculates celsius equivalent as a double

degreesC = (5 * (dblDegreesF - 32) / 9);

//prints the inputted integer then its equivalent celsius with one decimal

System.out.println(degreesF + " fahrenheit = " + degreesC + " celsius.");

The problem is, that the degreesC prints out with like 8 decimal places behind it. I have looked at BigDecimal, DecimalFormat, ROUND_UP, etc.. but I cannot find what is appropriate, and how to implement it into my code. I am very new to Java and I find that Java API lacks examples very much. Thanks for all the help!

[1058 byte] By [eristica] at [2007-11-27 5:38:37]
# 1
Use DecimalFormat but note that it doesn't change the value. It simply gives you a String that represents the format you want.
floundera at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 2

if you just want the representation to be rounded use System.printf or String.format

System.out.printf("%.1f\n", degreesC);

orString formated = String.format("%.1f", degreesC);

rounding with BigDecimalBigDecimal big = new BigDecimal(degreesC);

big = big.setScale(1, RoundingMode.HALF_UP); // exact value

degreesC = big.doubleValue(); // rounding errors can happen here

without BigDecimaldegreesC = Math.floor(degreesC * 10.0 + 0.5) / 10.0;

[]

S_i_m_ua at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 3

Or String.format() whose usage is further described in the Formatter class http://java.sun.com/javase/6/docs/api/java/util/Formatter.html

The Java Developers Almanac 1.4 is a good source of examples

http://www.exampledepot.com/egs/java.text/FormatNum.html

[Edit] Slow! I was looking - unsucessfully - for some exmples of String.format(). You could google for this: it closely resembles the printf() function of C and other languages.

pbrockway2a at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 4

rounding with BigDecimal

BigDecimal big = new BigDecimal(degreesC);

big = big.setScale(1, RoundingMode.HALF_UP); // exact value

degreesC = big.doubleValue(); // rounding errors can happen here

--

I used this method and it worked. I am reading the API on BigDecimal but it is very very difficult to understand. Would you mind explaining it a little bit. Why did you call it "big"? Or is that part of the syntax? Also, why would big.doubleValue have rounding errors when the line above it you say it is exact ? Thanks for the help!

I was just going to divide and multiply by 1000 or whatever I needed to get the right decimal, but I knew there had to be a function built into Java that I could use. Basically, I am trying to learn all the methods and classes instead of trying to go around them :)

eristica at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 5

> bit. Why did you call it "big"? Or is that part of

because it's easy to type ;--) , it's just a (variable) name.

> the syntax? Also, why would big.doubleValue have

> rounding errors when the line above it you say it is

> exact ?

doubleValue() returns a double which has a limit number of bits for representing numbers (more than enough for degrees). Try this

System.out.println(1.04 - 1);

results in something like "0.040000000000000036" == same problem you had converting degrees.With BigDecimal you decide how many decimal digits you need.

S_i_m_ua at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 6

Suppose you do the F to C conversion and obtain degreesC=1.4500000000.

Check this out:import java.math.BigDecimal;

import java.math.RoundingMode;

public class Round {

public static void main(String[] args) {

double degreesC = 1.45;

System.out.println(degreesC);

BigDecimal big = new BigDecimal(degreesC);

System.out.println(big);

big = big.setScale(1, RoundingMode.HALF_UP); // exact value

System.out.println(big);

degreesC = big.doubleValue(); // rounding errors can happen here

System.out.println(degreesC);

// same thing with a different BigDecimal constructor

System.out.println("");

big = new BigDecimal("1.45");

System.out.println(big);

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

System.out.println(big);

degreesC = big.doubleValue();

System.out.println(degreesC);

}

}

It has the output1.45

1.4499999999999999555910790149937383830547332763671875

1.4

1.4

1.45

1.5

1.5As you can see the BigDecimal constructor that takes a double will result in a BigDecimal that is a little less than 1.45 and which rounds, therefore, to 1.4 The other constructor - with a String argument - doesn't do this.

I would question whether you really need to use BigDecimal at all in this case. All you are trying to do is display a numeral (a string representing a numerical value) in a way that is not too long (only has 1 decimal place). This is really a question of formatting and not rounding. What I mean is that you are changing the appearance of degreesC when it is printed, not the value of degreesC: any change can only make it less accurate.

As such the problem is no different from formatting (preparing for display) a date or a boolean value or anything else. And its the formatting methods that were suggested earlier that are most natural for this, not numerical ones.

pbrockway2a at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 7

@pbrockway2

I see what you mean. This is definately a formatting issue than a numerical one. So, what would I use to merely truncate, rather than round? Also, what kind of variable is "big"? Is it a double/float? it appears that it is its own kind.Thank you very much for the explanation, it is much much more helpful than the API which reads too technical for me.

eristica at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...
# 8

As you know doubles and floats only use a (quite small) number of bits. Consequently there will always be some imprecision. BigDecimal is a class representing numerical magnitudes that does not suffer from this restriction. Big decimal numbers will "grow" as much as you want them to - subject only to the amount of memory and disk space in your computer, and the amount of time you can wait for arithmetic to be done on them.

"it appears to be its own kind" is about right.

Back to your question concerning degreesC. There is no reason why you shouldn't use the rules that we all learnt at school: the 5's going up business (rather than truncating). But realise that this is a matter of changing the appearance not the value of degreesC.value appearance

1.43 --> "1.4"

1.44 --> "1.4"

1.45 --> "1.5"

1.46 --> "1.5"(Writing the 1dp strings as strings with quote marks, not as numbers)

You can do this either with DecimalFormat as flounder suggested (and the Almanac link I gave has examples of this). Or with String.format() which I suggested (S_i_m_u's post gave examples of this.)

The example given of using BigDecimal for this is - I would submit - buggy in that it sometimes rounds up and sometimes truncates, depending on which way the wind is blowing. But, further, it seems a bit odd to employ a class with potentially infinite precision in order to solve a problem involving a single decimal place. It looks like what one of my teachers used to describe as "using a steam hammer to crack a walnut". The wrong tool for the job.

pbrockway2a at 2007-7-12 15:12:26 > top of Java-index,Java Essentials,New To Java...