Java StackOverflowError - java

...
float value = Float.parseFloat((String)model.getValueAt(e.getLastRow(), 1));
DecimalFormat dec = new DecimalFormat("#.###");
model.setValueAt(dec.format(value), e.getLastRow(), 1);
...
at the third line i'm getting the stackOverflowError exception. What I'm intending to do is getting a JTable cell value from an Object, converting it to a float, limiting it to 3 decimal places, and finally convert to String and set the value with 3 decimal places at the cell.
I guess the problem is I'm changing the value, and entering the function again and again. So the StackOverflow is due to that. Question is, how can i fix this?
Complete function at: Java: Converting data types
(Sorry for posting twice... It was a different question, and the solution drove me to a different problem)

The problem is that setValueAt() will, as part of its implementation call tableChanged() on all registered listeners, including this one.
In order to avoid this, simply check whether the value in the cell is already in the desired format as the first thing in your method, and don't do anything if it is.

Just don't call model.setValueAt() if value of the cell is not changed.
It should stop the recursion.

I think this task is usually accomplished by setting a custom editor to the table. So that it formats all input data to a desired form. See this answer.

Perhaps you need something like
String text = (String) model.getValueAt(e.getLastRow(), 1);
String text2 = new DecimalFormat("#.###").format(Float.parseFloat(text));
if (!text.equals(text2))
model.setValueAt(dec.format(value), e.getLastRow(), 1);

Related

How do I format a JSR-385 Quantity with fixed number of decimal digits?

I'm trying to convert hard-coded formatting to a Java Units API implementation.
The existing code outputs (for this example, the temperature value in degrees) with two decimal places. For example, 38.70°C. While I'd like to allow the user to specify their own formatting code (which is the end-goal of the change), I think it would be useful to keep the legacy behavior to give people a chance to migrate.
The existing code looks like:
return String.format("%.2f\u00B0C", this.temperature);
The code I'm trying to use looks like:
DecimalFormat numberFormat = (DecimalFormat) DecimalFormat.getInstance();
numberFormat.setMinimumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
NumberDelimiterQuantityFormat formatter =
NumberDelimiterQuantityFormat.builder()
.setNumberFormat(numberFormat)
.setDelimiter("")
.setUnitFormat(SimpleUnitFormat.getInstance())
.build();
return formatter.format(temperature);
It does format, but not with the specified precision. I'd expect 38.70°C but instead get 38.70000076293945℃.
If I just do
numberFormat.format(temperature.getValue().floatValue());
then it does format correctly ("38.70"). So I think the DecimalFormat is basically OK.
I considered just manually building my formatting. However that doesn't really work for what I want to do - pass in the NumberDelimiterQuantityFormat (or applicable interface).
Can anyone suggest an appropriate way to format a Quantity<> with fixed decimal precision?
First off, I'm completely unfamiliar with the Java Unit API and this implementation, but this seemed like an interesting question, so I looked into it.
I had a look at the implementation of NumberDelimiterQuantityFormat and right there in the implementation of the format method it modifies the maxiumFractionDigits of the NumberFormat depending on the fraction
if (quantity != null && quantity.getValue() != null) {
fract = getFractionDigitsCount(quantity.getValue().doubleValue());
}
if (fract > 1) {
numberFormat.setMaximumFractionDigits(fract + 1);
}
Source
This makes little sense to me for two reasons:
It negates the whole reason to have a NumberFormat in the first place especially in context with floating point numbers where it's virtually impossible to avoid superfluous fraction digits.
It modifies the internal state of the NumberDelimiterQuantityFormat in a method where it isn't expected.
I should have checked first, but there is actually an issue about this, which is "being analyzed" for several months now. Maybe it would make sense to ask in there.

BigDecimal precision above 1E22

for some reason I found myself coding some piece of software, that should be able to perfom some astronomic calculations.
While most of it will be about transfering the correct formula into Java, I found an annoying Problem right at the verry beginning of my "test how to calculate big numbers".
Well... Imagine the Sun (our Sun), which has a mass of (about and rounded, for more easy explaining) 10E30 kg. Ten with 30 following Zeros. All native datatypes are just unusuable for this. To mention: I KNOW that I could use 3000 to calculate things and just add trailing zeros in the output-view, but I hoped to keep it as precise as possible. So using short numbers will be my last resort only.
Comming to the Problem. Please have a look at the code:
BigDecimal combinedMass = new BigDecimal(1E22);
int massDistribution = 10;
Integer mD1 = massDistribution;
Integer mD2 = 100 - massDistribution;
BigDecimal starMass;
BigDecimal systemMass;
systemMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD1.toString()));
starMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD2.toString()));
System.out.println((systemMass).toEngineeringString());
System.out.println((starMass));
It will output 1000000000000000000000 and 9000000000000000000000, whats exactly what I did expect. But look at the combineMass Field. If I raise it to 1E23, the Output will change
I get 9999999999999999161139.20 and 89999999999999992450252.80...
So I know I could use jut BigInteger, because its more reliable in this case, but for the sake of precicion, sometimes the BigWhatEver may drop to something like 50.1258
Plus, I hope to get the 10.xE30 as output, whats only possible using bigDecimals.
I want to know: Is there no way avoidng this (that error appers above 1E23 for every value I tried), while keeping the ability to calculate Floating-Points? Should I cut the After-Decimal-Separator-Values for this Field to two digets?
And for something more to wonder about:
System.out.println(combinedMass.precision());
in relation with the code above will provide 23 for that case, but En+1 for most other values (Thats was when I grow really confused)
Thanks for advise.
You're using basic types without realizing it:
new BigDecimal(1E22);
Here, 1E22 is a primitive double, and you already lost precision by using it.
What you want is
new BigDecimal("10000000000000000000000");
or
new BigDecimal(10).pow(22);

Java getBytes() method is stripping .00 from numbers in my String

I'm generating a csv file and I have a bunch of numbers without decimal points and I'm being required to put .00 for those cases, I'm using:
DecimalFormat f = new DecimalFormat("#.00");
So fa so good I can see a string looking this way:
String myStringWithDecimalPoints = "124.00, 24567868.00, 5.00"
but when I do:
out.write(myStringWithDecimalPoints.getBytes());
I get in my csv:
124, 24567868, 5
Why is this happening?
Any workarounds? (it does have to be CSV and .00 must appear)
You have to be careful with how you view your data, especially in spreadsheets like Excel where the format of the output depends on the type of the cell. It may or may not show decimal values.
A note for the future, with a call like
out.write(myStringWithDecimalPoints.getBytes());
you can safely assume that Java is writing all the bytes to the OutputStream. If you're not seeing the same thing in the receiving side, then the receiving isn't being done like you would expect.
Most likely there is some confusion between the value of your original string, and how your string appears when you output it in certain ways using your formatter. This does not necessarily mean that your "original" string has been altered.
We could say with greater certainty if you provided a more complete code example.

Inserting custom String between number and decimal - Java DecimalFormat

Hello and thank you in advance for the help.
I am having some trouble formatting using a Java function to mark up a price in HTML.
It seems that, no matter what I do, I cannot insert custom content between the numbers and the decimal (throws Illegal Argument Exception). Is there any known way to achieve the following:
NumberFormat nf = getNumberFormat("'<span class=\"dollars\">'##'</span></span class=\"decimal\">'.'</span></span class=\"cents\">'00'</span>'", locale);
nf.format(number);
Assume locale and number are correctly initialized.
If you look at the docs for DecimalFormat you'll see that they talk about the prefix and the suffix text - but not putting arbitrary text within a number.
It sounds like you should basically write this bit of formatting yourself - possibly using DecimalFormat for each section of the number.
You might consider using String.format(String pattern, Object... arguments). You can pass your simply formatted numbers as arguments.

Java string to double conversion

I've been reading up on the net about the issues with handling float and double types in java. Unfortunately, the image is still not clear. Hence, i'm asking here direct. :(
My MySQL table has various DECIMAL(m,d) columns. The m may range from 5 to 30. d stays a constant at 2.
Question 1.
What equivalent data-type should i be using in Java to work (i.e store, retrieve, and process) with the size of the values in my table? (I've settled with double - hence this post).
Question 2.
While trying to parse a double from a string, i'm getting errors
Double dpu = new Double(dpuField.getText());
for example -
"1" -> java.lang.NumberFormatException: empty String
"10" -> 1.0
"101" -> 10.0
"101." -> 101.0
"101.1" -> 101.0
"101.19" -> 101.1
What am i doing wrong? What is the correct way to convert a string to a double value?
And what measures should i take to perform operations on such values?
EDIT
This is the code -
System.out.println(dpuField.getText());
Double dpu = new Double(dpuField.getText());
System.out.println(dpu);
Yes, the problem lies with getText() reporting the wrong value of the dpuField.
This method is called on the JTextField keyTyped event. So what's going wrong here?
EDIT 2
Looking at :
http://journals.ecs.soton.ac.uk/java/tutorial/post1.0/ui/keylistener.html
Apparently, keyTyped() does not give me the keycode. I'll have to switch to keyRealeased()
What equivalent data-type should i be using in Java to work (i.e store, retrieve, and process) with the size of the values in my table? (I've settled with double - hence this post).
Since it's a DECIMAL field, you should prefer java.math.BigDecimal. You can store it in DB using PreparedStatement#setBigDecimal() and you can retrieve it from DB using ResultSet#getBigDecimal().
While trying to parse a double from a string, i'm getting errors
This can't be true. The problem lies somewhere else. Maybe it is just not returning the data you expect to be returned or you are not using/debugging the values you expect them to be.
if you need exact precision without rounding errors, you should use a BigDecimal.
Your code looks OK - could it be that dpuField.getText() somehow cuts the last character from the string values you list above?
Update: you say
Yes, the problem lies with getText() reporting the wrong value of the dpuField. This method is called on the JTextField keyTyped event.
Could it be that getText() returns the value of the field before the last typed key is actually appended to it?
For decimal, I believe you risk losing precision if you don't use a BigDecimal on the Java side, as some decimal fractions can't be stored as a binary fraction.
Prefer Double.valueOf(String) over the constructor, but that's a valid way. Something else must be going on (i.e. I doubt those are the actual String values you're passing in).
Question1: It's bad idea to map DECIMAL columns to Double, usually the BigDecimal is the correct type. http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html#1055175
Question 2: You are doing something wrong; print the String value before converting.

Categories