Format Issue while reading excel data into Java - java

I am reading Excel data using java apache. I got format issue while reading double value such as 869.87929 (in excel) into 869.8792899999999 (in java).
I'm using following files to read excel data.
1. Schema.csv: SheetName,2-int-Double
2. File.xls:
col1 | col2
123 | 869.87929
Sample code:
if(type.equals("Double")){
Double fval=Double.parseDouble(content[i-1]);
String sval=fval.toString();
listObjects.add(new Double(Double.parseDouble(sval)));
}
Note: type from schema.csv & content [] value from file.xls

There is no point converting number back and forth to Strings as this shouldn't do any thing useful.
Try doing
listObjects.add(new BigDecimal(content[i-1]));
with rounding you can do
listObjects.add(new BigDecimal(content[i-1]).setScale(9, RoundingMode.HALF_UP));
though I suspect the rounding error has occurred before this point as this should do basically the same thing as
listObjects.add(new Double(content[i-1]));
with rounding you can do
double d = Double.parseDouble(content[i-1]);
double round9 = Math.round(d * 1e9) / 1e9;
listObjects.add((Double) round9);
These are much the same as the number is within the precision of double and there should be no additional error here (i.e. the error is likely to be before this point)

Double is not good for preserving precision. Preffered is using BigDecimal. I believe this is your problem.
https://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal

If you use Apache POI - you can use getCellType()==Cell.CELL_TYPE_NUMERIC comparison and getNumericCellValue() from Cell interface.

Related

DoubleValue of BigDecimal provided wrong output

Using java 11 and Intellij Idea.
I'm in the situation where I get a string of data from an external system and need to reformat this. In the current setup I have this line to extract the value for a sales price:
BigDecimal sellingPrice = BigDecimal.valueOf(Double.parseDouble(somesalesprice));
According to the debugger, the output value of sellingPrice = "4.350000000"
Now when I convert this according to this line of code:
long roundedSellingPrice = (long) (sellingPrice.doubleValue() * 100);
the result turns out to be "434". As can be seen, 1 (cent) has magically disappeared. I double-checked the values and this consistent. Out of the 500+ dataset that I'm working with, approx. 40 other records seem to have this problem. For the majority it seems to be going just fine.
I cannot find anything common between these records.
Also, it turns out, the result is always rounded down by 1 cent, never up.
Wonder what this could be?
As weird as it sounds for the data of types Float and Double the precision is not very good. Use BigDecimal for all the calculations. That's the short answer.
In Addition, when you parse a String to any numerical type you have to deal with exceptions. Sometimes it makes sense and sometimes it doesn't. For the case when you don't care about exception I wrote a utility that parses string to any numeric value and if parsing fails it returns a default value. In case you want your exception messages to be printed into log the same utility optionally may print exception messages into a log. See methods:
public static java.math.BigDecimalparseStringToBigDecimal(java.lang.CharSequence num, java.math.BigDecimal defaultValue) and
public static java.math.BigDecimal parseStringToBigDecimal(java.lang.CharSequence num,
java.math.BigDecimal defaultValue,
java.lang.String nullOrEmptyStringErrorMessage,
java.lang.String numberFormatErrorMessage)
Those methods can be pretty useful. The utility is comes with Open Source MgntUtils library written and maintained by me. You can get it as maven artifacts or at Github

Java to C# format specifiers

I am new to C# having used Java.
I am looking to output an expression of 4.5 - 2.7... In Java I would simply write System.out.format("%.2f\n", 4.5 - 2.7);
In C#, I have used Console.WriteLine(4.5 - 2.7); but I am looking to print 2 decimal places.
Could someone be so kind as to explain how I achieve this?
Use String.Format (Link To Documentation)
Use the format {Parameter Number:Decimal Places}
Console.WriteLine(String.Format(" We are going to format 15.6345 as {0:0.00}",15.6345));
Test it here!.
Good luck!
EDIT / Clarification
By Parameter Number, String.Format takes all other inputs after the first input of a string to be values to format and place into the string.
Every time {x:yyz} appears in the string, System.String.Format will format x in the style yyz, where x is the index of the value passed in.
In my example above, 15.6345 is x, and the format 0.00 is yyz.
You could format 2 numbers or repeat one by going:
Console.WriteLine(String.Format(" We are going to format 15.6345 as {0:0.00} , the format 3.123 as 3.1 {1:0.0} , then repeat 15.6345 as 15.6 {0:0.0}",15.6345,3.123));

Java float to int conversion error

Hey Guys I am using a list of lists in java.The list is called deg_grp and the code below shows the output of the deg_grp at a particular index j.
for(int k=0;k<deg_grp.get(j).size();k++)
{
System.out.println(deg_grp.get(j).get(k));
}
The output is:
1.0
2.0
4.0
6.0
8.0
So these are my values. But when I replace the print command by
System.out.println((int)deg_grp.get(j).get(k));
It is throwing me an error.I need to perform int conversion for indexing purposes later on.The error is:
incompatible types: Float cannot be converted to int
So I am unable to run the code. Kindly help me out. Thanks :)
Use Float#intValue() for your conversion.
You can't unboxed and convert types in one step. You can do (int)(float) f however I suggest not using Float, use double or Double for more precision and using Math.round(d) to round the result, to minimise errors.
System.out.println(Math.round(deg_grp.get(j).get(k)));

Instances went wrong from csv to weka

.csv
100387C,254,73,93
100388D,2047,60,98
100388D,2736,62,9
100389E,951,82,90
100390F,2048,91,98
100411C,254,50,96
100412D,047,75,9
.arff
#relation test
#attribute Admno {100387C,100388.0,100389E,100390.0,100411C,100412.0}
#attribute Code {254,2047,2736,951,2048,254,047}
#attribute ore numeric
#attribute tend numeric
100387C,254,73,93
100388.0,2047,60,98
100388.0,2736,62,9
100389E,951,82,90
100390.0,2048,91,98
100411C,254,50,96
100412.0,047,75,9
If you were to notice the different between this two data after converting was
from D to .0 on #attribute Admno. The file conversion I was using are below. So I was wondering what went wrong on the conversion. Thanks
CSVLoader loader = new CSVLoader();
loader.setSource(new File("C:\\test.csv"));
Instances data = loader.getDataSet();
ArffSaver saver = new ArffSaver();
saver.setInstances(data);
saver.setFile(new File("C:\\test.arff"));
saver.writeBatch();
The reason you are getting 100388D as 100388.0 and 100390F as 100390.0 is because the values are ending with D and F respectively. In Java, this means the values are Double and Float (D stands for Double and F stands for Float). That is why when Weka is converting them into nominal values, it is believing that the values should be Double or Float and hence the .0 instead of D and F.
You can find a discussion here and the related documentation here.
To the best of my knowledge, there is no straight forward way to overcome this in Weka. But if this is an ID and does not take part into classification or clustering, then you can have the facility to ignore this attribute when you build a model based on this data and apply it on your test data.
Another way to overcome this is to change this attribute's values to some values that don't end with neither D nor F.

Storing big numbers as they are

I'm using java and Apache derby to create a project that deals with big numbers. Everything is going fine except when i store big numbers.
For eg. when i save 1000000000 through my java class to a derby table, it automatically becomes 1.0E9. When this value is retrieved in another form it is displayed like 1.0E9. How can I stop this? I'm using float data type to do this.
In other words, how can I save 1000000000 as 1000000000 and not 1.0E9
Like above said you could use a BigInteger or you could just covert 1.0E9 to what the number actually is. 1.0 x 10^9.
1.0e9 is the same as 1000000000; it's just a representation issue. You just have to apply the proper formatters when transforming it to a string.
Two things that would make this easier are to use the NUMERIC column type in Derby, and also use either BigDecimal or BigInteger data types in your Java code, or possibly a long if you're confident that the long can hold the values in your problem domain.
import java.math.BigInteger;
//...
//...
//...
BigInteger store = new BigInteger("1000000000");

Categories

Resources