BigDecimal precision above 1E22 - java

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);

Related

How can I convert something to double?

I have an object from an implemented class ReportManager. Now getReport() is a number like 0.23 with the data type report. But I want this number to be a double so I can work with it.
I cannot change the class, because it is implemented in the Java compiler (it is for writing macros for a program).
Does anybody have a suggestion how I could handle it? I checked the API and there is no function implemented that could help me.
EDIT: I do have the situation: I want to calculate the Center of Pressure of an object in my simulation. So I need the moment in that position to be 0.
Now: This is how the automated macro ask the value of the Moment:
MomentReport momentReport_0 =
((MomentReport) simulation_0.getReportManager().getReport("Moment 1"));
Now I want to take the abs of it, because I don't mind if it's positive or negative.
while(Math.abs(momentReport_0) > 0.2)
(Do iterate and change position.) At the end I want to println the the position.
simulation_0 is an object of Simulation. I could copy a part of the API if it's needed. Just don't know which class documentation would help.
You can cast the number to a double so that you can work with it, assuming it's returning you a single-precision float at the moment.
double result = (double) reportManager.getReport();
I recommend you read up on what typecasting is so that you can better understand what's going on here, as there would be some situations where it's unsafe to cast:
https://en.wikipedia.org/wiki/Type_conversion

Graphing Time per trip using JFreeChart

System.out.println("Hello all that use Java && JFreeChart!");
I am writing an application that allows cyclists, such as myself, to keep track of their average speed, distance, and time for a given trip. They are to enter that data, and then a JFrame pops up with their graphed information. I have a class that converts the elapsedTime to a String format (for display purposes!), but I don't think JFreeChart can take it in for a Range value. In fact, I checked out their API documentation, http://www.jfree.org/jfreechart/api/javadoc/index.html , and quickly found out that Range() only takes parameters of type double! Not String, not Time, double. This is a letdown because I intended to set the interval of graph displayed equal to the interval formed by their minimum time and maximum time. Is there any way around this?
From my understanding of the question, you could try:
double value = Double.parseDouble(string);
However, this will obviously not work if you put in a time-based value. From the comments you have made, perhaps a TimeSeriesChart from ChartFactory could solve your problem.
It seems like the ChartFactory.createTimeSeriesChart() is the way to go, but it is the most disappointing way to go. Sure, you can switch the axes, but this does NOTHING to the data! The smartest way to approach this would be an XYLineChart, and then use a RelativeDateFormat : http://www.jfree.org/jfreechart/api/javadoc/index.html . That way, your range values go in as type long, and then you can just bring in a DateAxis that has RelativeDateFormat. Problem solved.

Problems with Polynomial.java zeros method

Here is the location of the source code (using Dropbox).
The problem is in the fact that it doesn't evaluate zeros properly.
For example: x^2-2x-8 should equal the zeros of {-4, 2}, but instead I get a long exponential value like -4+34534....E-25<i>i</i>.
It does work for polynomials with single roots (such as x<sup>2</sup>+4x+4, root = {-2})
Can anyone spot the problem, it's been frustrating me for weeks. This is NOT a homework assignment, this is something I work on in my free time.
I've run into problems like this before and decided to switch to a different (math-oriented) language. You could try using floats instead of doubles, which may do the trick, but would probably bear problems of their own. Or you could write a method that filters out anything smaller than 1E-10 or something along those lines. Another alternative (which may or may not be relevant here) would be to use JLink.

Handling division by zero in graphics code

I'm writing a library for procedural image generation (Clisk) which allows users to define their own mathematical functions to generate images.
It's clearly possible for them to define a function which could result in a divide by zero for some pixels, e.g. (pseudocode)
red = 1.0 / (xposition - 0.5)
This would result in a divide by zero whenever xposition = 0.5 (the middle of the image)
Ideally I don't want image generation to crash... but at the same time I don't want to create a clunky hack to ignore divide by zeros that will cause problems later.
What would be a good, robust, systematic approach to handling these cases?
Ideally I don't want image generation to crash... but at the same time I don't want to create a clunky hack to ignore divide by zeros that will cause problems later.
(I'm assuming you mean the snippet to be an example of some user-supplied code ...)
Clearly, if the user-supplied code could throw exceptions, then you can't stop that happening. (And the advice to check before division is obviously irrelevant ... to you.)
So what could you do apart from "crash"? Generate an empty image? Ignore the user's function? You'd be producing garbage ... and that's not what the user needs.
You certainly can't reach in and fix his / her java code. (And if that snippet is meant to be code written in some custom language, then you can't reach in and correct that either. You / your library doesn't know what the user-supplied code should be doing ...)
No. I reckon that the best answer is to wrap any unexpected (unchecked) exceptions coming out of the user-supplied code in an exception of your own that tells the user clearly that the error occurred in his code. It is then up to the application code calling your library code whether to deal with the exception or "crash".
If you are asking for a "good, robust, systematic approach" for users to write their functions, I think you are barking up the wrong tree. And it is not really your concern ...
I'm not a graphics programmer really, but you could do
private static final double MIN_X = 0.0000001
red = 1.0 / Math.max(xpos - 0.5, MIN_X);
Obviously, you will probably have to drop an absolute value in there if you allow negatives
You could always just supply a parameter asking them what to do on divide-by-zero. It's their code, after all - they should know what's best for their case.
Then the question becomes, what's a reasonable default for that parameter? I'd say "return 0.0" or "throw an exception" are both reasonable for this application. Just make sure you document it.

Follow-up to how to get an Integer as result

I asked a question How to get an Integer as result?
The suggested solution with decimalFormat works, but my problem is that I want my data not only to be presented as ##.0 but to be like this, because in the end of my program I use them. So I want to be exactly in that type; otherwise I get the wrong final number. Any ideas?
EDIT:
let me be more specific. i get 12,344 from my first calc, 14,4566 from my second and 18,5644 from my third.that makes a sum 45.365.Now,if i do then 12,3 , 14,4 and 18,5 the sum is 45.2...thats the point of my answer.i want to have 45.365 at the end and not 45.2
The problem seems to be a design issue with your app.
On the one hand, you want to display the results to the user with 1 digit after the decimal point.
In the other hand, you actually want to keep the extra precision and use it for follow-up calculations.
I would argue that this is a poor user interface model. IMO, the numbers that the user sees should be the numbers that go into the calculations. This means you should either:
show the user more digits after the DP in the first place (or at least give a visual indication that there are more digits), or
do the calculations using the rounded / truncated values ... as displayed to the user.
Once you have figured out a consistent user interface model, the required implementation approach should be much clearer to you.

Categories