Java serialize double - java

I want to serialize/deserialize doubles to a readable String. I'm happy to lose any accuracy beyond the 6th dp.
Whats the correct approach for doing this?
I'm concerned about System.out.println(1.03 - .42) printing 0.6100000000000001 and not 0.61.
Thxs.

If you want the value for testing purposes, Double.toString(double) could be good.
If you want a more readable number (1.01 instead of 1.01000000000587732, for example), you can use DecimalFormat (http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html) or BigDecimal:
BigDecimal bd = BigDecimal.valueOf(double)
BigDecimal bd2 = bd.setScale(6, RoundingMode.HALF_UP); // six decimal
String out = bd2.toString();
String out2 = bd2.toPlainString();
Edit: after the user edit, I think a correct approach would be:
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(1.03 - .42));

Take a look at java.lang.Double.toString() and java.lang.Double.valueOf(String s).

The simplest approach is to use PrintWriter and BufferedReader.
double[][] doubles = new double[10][10];
for(double[] ds : doubles)
for(int i=0;i<ds.length;i++)
ds[i] = Math.random() * 100;
PrintWriter pw = new PrintWriter("double.tsv");
for(double[] ds : doubles) {
for(double d: ds)
pw.printf("%.6f\t", d);
pw.println();
}
pw.close();
BufferedReader br = new BufferedReader(new FileReader("double.tsv"));
String line;
while((line = br.readLine())!=null) {
String[] words = line.split("\t");
for (String word : words) {
double d = Double.parseDouble(word);
System.out.print(d+"\t");
}
System.out.println();
}
prints
72.520491 85.341994 21.958533 48.914986 14.959155 54.398293 54.438528 6.265907 77.654032 94.363109
65.594713 66.943443 69.891651 3.62663 13.445234 3.281239 99.897356 53.072258 11.931774 83.802643
17.387541 56.598334 90.104328 69.379567 95.631605 34.931461 73.336693 21.300139 50.511963 79.326218
61.844333 20.076352 81.668206 69.500067 45.936303 80.639298 86.534122 51.031074 89.718252 89.510961
41.923934 31.450051 35.373463 82.607984 69.796802 11.387551 28.684281 28.524173 3.926274 27.390139
43.116206 81.455006 52.424004 46.399187 84.572294 20.368705 7.414759 18.389408 91.835487 96.594918
87.632357 63.293224 8.751766 70.693449 12.30385 41.090964 93.36716 31.281827 95.411907 29.825814
46.516716 53.442007 18.273036 15.306335 87.773823 72.392803 85.34191 78.388259 80.203328 19.306142
93.249744 50.981212 7.02211 90.461556 46.307283 0.304891 33.055868 98.374818 33.050704 92.423133
41.791121 84.102962 37.881277 80.713237 24.856496 53.619386 99.447379 62.681776 14.927559 37.969094

Related

How to solve the error for DecimalFormat on a calculator app [duplicate]

This question already has answers here:
Problems using DecimalFormat
(6 answers)
Closed 2 years ago.
I am making a calculator app.
workingsTV is the place where calculating is shown.
resultsTV is the place showing the result of calculating.
workings is doing math by using rhino's library.
I want to add a comma at every three digits on both workingsTV and resultsTV.
I tried to use it like this for resultsTV.
DecimalFormat df = new DecimalFormat("###,###.####", new DecimalFormatSymbols(Locale.US));
result = Double.parseDouble(df.format(result));
But then the app was closed when to show result
This is the error message
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.NumberFormatException: For input string: "1,235"
Here is the top part of the code
public class MainActivity extends AppCompatActivity {
TextView workingsTV;
TextView resultsTV;
String workings = "";
String CLEAR_INT_TEXT;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTextView();
}
private void initTextView()
{
workingsTV = (TextView)findViewById(R.id.workingsTextView);
resultsTV = (TextView)findViewById(R.id.resultTextView);
}
private void setWorkings(String givenValue)
{
workings = workings + givenValue;
workingsTV.setText(workings);
}
public void equalsOnClick(View view)
{
Double result = null;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");
try {
result = (Double) engine.eval(workings);
if (result != null)
{
DecimalFormat df = new DecimalFormat("###,###.####", new DecimalFormatSymbols(Locale.US));
result = Double.parseDouble(df.format(result));
int intVal = (int) result.doubleValue();
if (result == intVal)
{//Check if it's value is equal to its integer part
resultsTV.setText(String.valueOf(intVal));
}
else
{
resultsTV.setText(String.valueOf(result));
}
}
}
I'm using that function to convert double to formatted string
public String formatDouble(double value, int digits) {
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
decimalFormatSymbols.setGroupingSeparator(',');
decimalFormatSymbols.setDecimalSeparator('.');
DecimalFormat decimalFormat = new DecimalFormat("###,##0.00", decimalFormatSymbols);
decimalFormat.setMinimumFractionDigits(digits);
decimalFormat.setMaximumFractionDigits(digits);
return decimalFormat.format(value);
}
In your code, you already have an result value here result = (Double) engine.eval(workings);. Why do you want get it second time? In addition, using formatted string, who may contains illegal character for double (comma char).
Just remove that two lines
DecimalFormat df = new DecimalFormat("###,###.####", new DecimalFormatSymbols(Locale.US));
result = Double.parseDouble(df.format(result));
And format result value when you'll set it to TextView, example with my function:
resultsTV.setText(formatDouble(result, 4));
At the end of equalsOnClick() method, you should set result or intVal to the workings variable to make it ready for next operations.
workings = String.valueOf(result);
Try this:
import java.text.NumberFormat;
import java.util.Locale;
Locale locale = new Locale("en", "US");
NumberFormat fmt = NumberFormat.getCurrencyInstance();
System.out.println(fmt.format(1235.00));

how to group 59 elements into one element in arraylist?

so, i have a program that read value and its year from a textfile that starts from 1960 till 2018. each indicator code have different values but the year stays the same, 1960-2018. i have successfully read the textfile and store it in the arraylist.
however, values and its years from one indicator is not grouped in one element. but instead, it groups them one value(and its year), one element. AND let's say i have 2 indicator code, 59 values for each indicator code. they're all mixed up in 118 elements. i wanted them in 2 elements.
how to solve this problem so that each indicator code and its data(years and values) is in one element?
myLinkedList bigdata = new myLinkedList();
ArrayList <MyData> data = new ArrayList();
MyData d1;
File inFile2 = new File ("indicator2.txt");
FileReader fr2 = new FileReader (inFile2);
BufferedReader br2 = new BufferedReader(fr2);
String str2 = br2.readLine();
while(str2 != null ){
StringTokenizer st = new StringTokenizer(str2,";");
String cCode = st.nextToken();
String iName = st.nextToken();
String iCode = st.nextToken();
for (int j = 0; j < 59; j++){
String v = st.nextToken();
int year = 1960 + j;
d1 = new MyData (year,v);
data.add(d1);
}
Indicator idct1 = new Indicator (cCode,iName,iCode,data);
bigdata.insertAtBack(idct1);
str2 = br2.readLine();
}
example of indicator2.txt:
MYS; Employment in industry (% of total employment) (modeled ILO estimate); SL.IND.EMPL.ZS; null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;31,72100067;31,62000084;32,01699829;32,22900009;32,34000015;32,23300171;33,6629982;31,76000023;31,70000076;32,18299866;33,11000061;31,97999954;32,02000046;30,12700081;29,72299957;30,26000023;28,45999908;28,68000031;27,01300049;27,73699951;29,08600044;28,56900024;28,36300087;28,02300072;27,51600075;27,48699951;27,39800072;27,30500031
(From left: cCode; iName; iCode; the values starting from 1960)
I believe the problem is that you're writing the data into the same ArrayList over and over again for all indicator codes. What if you moved the following statement:
ArrayList <MyData> data = new ArrayList();
Inside your while loop. Then you would be creating a new ArrayList for each indicator code when your save it to an Indicator object.
Generic types can be nested, so one solution would be to use an ArrayList of ArrayLists of MyData objects instead:
ArrayList<ArrayList<MyData>>

Convert to two decimal values after point

I want to convert 283.8 to 283.80
Used below code but didn't work...plz help
holder.walletBal.setText("$ " +String.format( "%.2f",283.8));
You can use DecimalFormat
Try this
DecimalFormat df = new DecimalFormat("#0.00");
Log.e("ANSWER",df.format(Double.parseDouble("283.8")));
OUTPUT
11-26 11:02:59.021 23883-23883/neel.com.rxjavademo E/ANSWER: 283.80
Please try with below code.
val value = 283.8f
String.format("%.02f", value))
I think it's a good way to put below method in your Utils class. It is working fine.
public static String roundToTwoDigit(Double paramDouble) {
if (!CommonUtils.isTextAvailable(String.valueOf(paramDouble))) return "";
DecimalFormat df = new DecimalFormat("0.00");
String strValue=df.format(paramDouble);
// String doubleValue= String.valueOf(Double.valueOf(strValue));
Log.e("ad","roundToTwoDigit ="+strValue);
return strValue;
}

Java.Lang.Double[] to Double[] issue for Polynomial from CSV

First of all thanks for your help in advance.
I'm writing an investment algorithm and am currently pre-processing CSV historical data. The end goal for this part of the process is to create a symmetrical co-variance matrix of 2k x 2k / 2 (2 million) entries.
The Java class I'm writing takes a folder of CSVs each with 8 bits of information, key ones being Date, Time & Opening stock price. Date & time have been combined into one 'seconds from delta' time measure and opening stock prices remain unchanged. The output CSV contains the above two pieces of information also with a filename index for later referencing.
In order to create the co-variance matrix each stock on the NYSE must have a price value for every time, if values are missing the matrix cannot be properly completed. Due to discrepancies between time entries in the historical training CSV, I have to use a polynomial function to estimate missed values, which then can be fed into the next process in the chain.
My problem sounds fairly simple and should be easy to overcome (I'm probably being a massive idiot). The polynomial package I'm using takes in two arrays of doubles (Double[] x, Double[] y). X pertaining to an array of the 'seconds past delta' time values of a particular stock and Y the corresponding price. When I try to feed these in I'm getting a type error as what I'm actually trying to input are 'java.lang.Double' objects. Can anyone help me with converting an array of the latter to an array of the former?
I realise there is a load of ridiculousness after the main print statement, these are just me tinkering trying to miraculously change the type.
Again thanks for your time, I look forward to your replies!
Please find the relevant method below:
public void main(String filePath) throws IOException {
String index = filePath;
index = index.replace("/Users/louislimon/Desktop/Invest Algorithm/Data/Samples US Stock Data/data-1/5 min/us/nyse stocks/1/", "");
index = index.replace(".us.txt", "");
File fout = new File("/Users/louislimon/Desktop/Invest Algorithm/Data.csv");
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
Reader in = new FileReader(filePath);
Iterable<CSVRecord> records;
try {
records = CSVFormat.EXCEL.withSkipHeaderRecord(true).parse(in);
} catch ( IOException ex ) {
System.out.println ( "[ERROR] " + ex );
return;
}
ZoneId zoneId = ZoneId.of("America/New_York");
boolean tmp = true;
Instant firstInstant = null; // Track the baseline against which we calculate the increasing time
ArrayList<Double> timeVals = new ArrayList<Double>();
ArrayList<Double> priceVals = new ArrayList<Double>();
for ( CSVRecord record : records ) {
if(tmp){
tmp = false;
}
else {
//System.out.println(record.toString());
String dateInput = record.get(0);
String timeInput = record.get(1);
Double price = Double.parseDouble(record.get(2));
LocalDate date = LocalDate.parse(dateInput);
LocalTime time = LocalTime.parse(timeInput);
//Double price = Double.parseDouble(priceInput);
LocalDateTime ldt = LocalDateTime.of(date, time);
ZonedDateTime zdt = ldt.atZone(zoneId);
Instant instant = zdt.toInstant(); // Use Instant (moment on the timeline in UTC) for data storage, exchange, serialization, database, etc.
if (null == firstInstant) {
firstInstant = instant; // Capture the first instant.
}
Duration duration = Duration.between(firstInstant, instant);
Long deltaInSeconds = duration.getSeconds();
double doubleDeltaInSeconds = deltaInSeconds.doubleValue();
timeVals.add(doubleDeltaInSeconds);
priceVals.add(price);
//System.out.println("deltaInSeconds: " + deltaInSeconds + " | price: " + price + " | index: " + index);
}
Double [] timeValsArray = timeVals.toArray(new Double[timeVals.size()]);
Double [] priceValsArray = timeVals.toArray(new Double[priceVals.size()]);
Double[] timeFeed = new Double[timeVals.size()];
Double[] priceFeed = new Double[priceVals.size()];
for(int x = 0;x<timeVals.size(); x++) {
timeFeed[x] = new Double (timeValsArray[x].doubleValue());
priceFeed[x] = new Double (priceValsArray[x]);
}
PolynomialFunctionLagrangeForm pflf = new PolynomialFunctionLagrangeForm(timeFeed,priceFeed);
}
According to the documentation, the PolynomialFunctionLagrangeForm constructor takes two double[] arrays, not Double[].
Hence you need to create a raw array and pass that:
...
double[] timeFeed = new double[timeVals.size()];
double[] priceFeed = new double[priceVals.size()];
for(int x = 0; x < timeVals.size(); x++) {
timeFeed[x] = timeValsArray[x].doubleValue();
priceFeed[x] = priceValsArray[x].doubleValue();
}
...
See also How to convert an ArrayList containing Integers to primitive int array? for some alternative ways to convert an ArrayList<T> (where T is a wrapper for a primitive type) to the corresponding raw array T[].
Note that there is also obviously a typo in your code:
Double [] priceValsArray = timeVals.toArray(new Double[priceVals.size()]);
needs to be
Double [] priceValsArray = priceVals.toArray(new Double[priceVals.size()]);

Extracting data from a collection in Java

I have a csv dataset like this:
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
I want to read this csv lines and provide the following output:
A has ran 30 miles with average of 15.
B has ran 30 miles with average of 20.
C has ran 4 miles with average of 4.
I want to achieve this in Java. I have done this in C# by using Linq:
var readlines = File.ReadAllLines(filename);
var query = from lines in readlines
let data = lines.Split(',')
select new
{
Name = data[0],
Miles = data[1],
};
var values = query.GroupBy(x => new {x.Name}).Select(group => new { Person = group.Key, Events = group.Sum(g =>Convert.ToDouble(g.Miles)) ,Count = group.Count() });
I am looking to do this in Java, and I am not sure if I can do this without using any third party library or not? Any ideas?
So far, my code looks like this in Java:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
String[] row = null;
for(Object object:content)
{
row = (String[]) object;
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n",Name,Miles);
}
reader.close();
}
I am looking for a nice way to get the total milage value for each name to calculate for the average.
As a C# developer, it is hard sometimes not to miss the features of linq. But as Farlan suggested you could do something like this:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
Map<String, Group> groups = new HashMap<>();
for(String[] row : content)
{
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n", Name, Miles);
if (groups.containsKey(Name)){
groups.get(Name).Add(Double.valueOf(Miles));
} else {
Group g = new Group();
g.Add(Double.valueOf(Miles));
groups.put(Name, g);
}
}
reader.close();
for (String name : groups.keySet())
{
System.out.println(name + " ran " + groups.get(name).total() + " with avg of " + groups.get(name).average());
}
}
class Group {
private List<Double> miles;
public Group()
{
miles = new ArrayList<>();
}
public Double total(){
double sum = 0;
for (Double mile : miles)
{
sum += mile;
}
return sum;
}
public Double average(){
if (miles.size() == 0)
return 0d;
return total() / miles.size();
}
public void Add(Double m){
miles.add(m);
}
}
Use Java's BufferedReader class:
BufferedReader in = new BufferedReader(new FileReader("your.csv"));
String line;
while ( (line = in.readLine()) != null) {
String [] fields = line.split(",");
System.out.println(fields[0] + " has ran " + fields[1] + " miles with average " + fields[2]);
}
There are quite a few ways to do this, some long-winded approaches, some shorter. The issue is that Java can be very verbose for doing simple tasks, so the better approaches can be a bit uglier.
The example below shows you exactly how to achieve this, par the printing. Bear in mind however, it might not be the best approach but I feel its more of the easier ones to read and comprehend.
final File csvFile = new File("filename.csv");
final Scanner reader = new Scanner(csvFile);
final Map<String, Integer> info = new HashMap<>(); //Store the data
//Until there is are no more lines, continue
while (reader.hasNextLine()) {
final String[] data = reader.nextLine().split(","); // data[0] = A. [1] = 10. [2] = USA
final String alpha = data[0];
if (!info.containsKey(alpha)) {
info.put(alpha, Integer.parseInt(data[1]));
} else {
int miles = info.get(alpha);
info.put(alpha, miles + Integer.parseInt(data[1]));
}
}
reader.close();
The steps involved are simple:
Step 1 - Read the file.
By passing a File into the Scanner object, you set the target parsing to the File and not the console. Using the very neat hasNextLine() method, you can continually read each line until no more exist. Each line is then split by a comma, and stored in a String array for reference.
Step 2 - Associating the data.
As you want to cumulatively add the integers together, you need a way to associate already passed in letters with the numbers. A heavyweight but clean way of doing this is to use a HashMap. The Key which it takes is going to be a String, specifically A B or C. By taking advantage of the fact the Key is unique, we can use the O(1) containsKey(String) method to check if we've already read in the letter. If its new, add it to the HashMap and save the number with it. If however, the letter has been seen before, we find the old value, add it with the new one and overwrite the data inside the HashMap.
All you need to do now is print out the data. Feel free to take a different approach, but I hope this is a clear example of how you CAN do it in Java.
Maybe you could try this Java library: https://code.google.com/p/qood/
It handles data without any getter/setters, so it's more flexible than LINQ.
in your case, file "D:/input.csv" has 3 columns:
NAME,MILES,COUNTRY
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
the query code would be:
final QModel raw = QNew.modelCSV("D:/input.csv")
.debug(-1);//print out what read from CSV
raw.query()
.selectAs("OUTPUT",
"CONCAT(NAME,' has ran ',SUM(MILES),' miles with average of ',MEAN(MILES),'.')")
.groupBy("NAME")
.result().debug(-1)//print out the result
.to().fileCSV("D:/output.csv", "UTF-8");//write to another CSV file

Categories

Resources