I am doing the following programming exercise: Grasshopper Debug. The statement is:
Debug celsius converter
Your friend is traveling abroad to the United States so he wrote a program to convert fahrenheit to celsius. Unfortunately his code has some bugs.
Find the errors in the code to get the celsius converter working properly.
To convert fahrenheit to celsius:
celsius = (fahrenheit - 32) * (5/9)
Remember that typically temperatures in the current weather conditions are given in whole numbers. It is possible for temperature sensors to report temperatures with a higher accuracy such as to the nearest tenth. Instrument error though makes this sort of accuracy unreliable for many types of temperature measuring sensors.
I have tried the following code:
public class GrassHopper {
public static String weatherInfo(int temp) {
double c=convertToCelsius(temp);
if (c < 0)
return (c + " is freezing temperature");
else
return (c + " is above freezing temperature");
}
public static double convertToCelsius(int temperature) {
double celsius = (temperature-32)*(5/9.0);
return celsius;
}
}
And we have found the following case:
test5
expected:<31.11111111111111[] is above freezing t...> but was:<31.11111111111111[4] is above freezing t...>
We thought it could be because of using double. Then we wrote the same solution using BigDecimal‽:
import java.math.BigDecimal;
import java.text.*;
public class GrassHopper {
public static String weatherInfo(int temp) {
BigDecimal c=convertToCelsius(BigDecimal.valueOf(temp));
NumberFormat oneDecimal = new DecimalFormat("#0.0");
c=c.toString().contains(".00") ? BigDecimal.valueOf(Double.parseDouble(oneDecimal.format(c))) : c;
if (c.compareTo(BigDecimal.ZERO) < 0)
return (c + " is freezing temperature");
else
return (c + " is above freezing temperature");
}
public static BigDecimal convertToCelsius(BigDecimal temperature) {
BigDecimal celsius = (temperature.subtract(BigDecimal.valueOf(32))).multiply(BigDecimal.valueOf(5/9.0));
return celsius;
}
}
Being the tests' result as follow:
test1
expected:<13.333333333333334[] is above freezing t...> but was:<13.333333333333334[4] is above freezing t...>
test5
expected:<-2.222222222222222[3] is freezing tempera...> but was:<-2.222222222222222[4] is freezing tempera...>
To know what is happening and try to fix it we have read:
https://docs.oracle.com/javase/7/docs/api/java/text/NumberFormat.html
How do i compare values of BigInteger to be used as a condition in a loop?
Could you help us‽
EDIT: Following the answer provided by @GovindaSakhare we could write:
public class GrassHopper {
public static String weatherInfo(int temp) {
System.out.println("original celsius temp: "+temp);
double c=convertToCelsius(temp);
double roundedValue=roundoff(c,15);
String result = "";
if (roundedValue < 0){
result=roundedValue + " is freezing temperature";
}else{
result=roundedValue + " is above freezing temperature";
}
System.out.println("result: "+result);
return result;
}
public static double convertToCelsius(int temperature) {
double celsius = (temperature-32)*(5/9.0);
return celsius;
}
public static double roundoff(double temperature, int precisionLevel) {
double prec = Math.pow(10, precisionLevel);
return Math.round(temperature * prec) / prec;
}
}
However, how do we know what precision level should be used‽
I ask because of, with the previous code, we observe the following behaviour:
Some test do pass:
test1
Log
temp: 56
result: 13.333333333333334 is above freezing temperature
test2
Log
temp: 23
result: -5.0 is freezing temperature
test4
Log
temp: 5
result: -15.0 is freezing temperature
And some others don't pass:
test3
original celsius temp: temp: 33
expected:<0.55555555555555[5]6 is above freezing ...> but was:<0.55555555555555[]6 is above freezing ...>
test5
original celsius temp: 54
expected:<12.22222222222222[1] is above freezing t...> but was:<12.22222222222222[3] is above freezing t...>
We think it has to be related to the last exercise's statement part:
"...Remember that typically temperatures in the current weather conditions are given in whole numbers. It is possible for temperature sensors to report temperatures with a higher accuracy such as to the nearest tenth. Instrument error though makes this sort of accuracy unreliable for many types of temperature measuring sensors. "
How would you think and act to solve this difficulty‽‽
EDIT2: Following @GovindaSakhare discussion link, we have found that test cases in Java are different than what we have expected. We tried the tip given by the user, vztot, and we used MathContext.DECIMAL128
We tried the following approach:
import java.math.*;
import java.text.*;
public class GrassHopper {
public static String weatherInfo(int temp) {
BigDecimal c=convertToCelsius(BigDecimal.valueOf(temp));
if (c.compareTo(BigDecimal.ZERO) <= 0)
return (c + " is freezing temperature");
else
return (c + " is above freezing temperature");
}
public static BigDecimal convertToCelsius(BigDecimal temperature) {
BigDecimal division = BigDecimal.valueOf(5).divide(BigDecimal.valueOf(9.0),MathContext.DECIMAL128);
BigDecimal subtraction = temperature.subtract(BigDecimal.valueOf(32),MathContext.DECIMAL128);
BigDecimal celsius = subtraction.multiply(division,MathContext.DECIMAL128);
return celsius;
}
}
However it gave errors in all tests:
test1
expected:<13.33333333333333[4] is above freezing t...> but was:<13.33333333333333[333333333333333333] is above freezing t...>
test2
expected:<-5.0[] is freezing tempera...> but was:<-5.0[00000000000000000000000000000000] is freezing tempera...>
test3
expected:<0.555555555555555[]6 is above freezing ...> but was:<0.555555555555555[555555555555555555]6 is above freezing ...>
test4
expected:<-15.0[] is freezing tempera...> but was:<-15.0[0000000000000000000000000000000] is freezing tempera...>
test5
expected:<34.44444444444444[] is above freezing t...> but was:<34.44444444444444[444444444444444445] is above freezing t...>
So then, we decided to think better, and we should use double as input parameters instead of ints:
public class GrassHopper {
public static String weatherInfo /*️ℹ️*/ (double temp) {
double c = convertToCelsius(temp);
if (c <= 0)
return (c + " is freezing temperature");
else
return (c + " is above freezing temperature");
}
public static double convertToCelsius(double temperature) {
return (temperature - 32) * 5/9.0;
}
}
So with this last version it does pass the tests.