2

I need to convert the following python code to Java and remember from the past that handling decimal values must be done carefully otherwise the results will not be accurate. My question is, can I use doubles for all non-interger values given doubles are more accurate that floats?

Here is my start of the conversion:

Python code

def degrees(rads):
    return (rads/pi)*180


def radians(degrees):
return (degrees/180 * pi)


def fnday(y, m, d, h):
a = 367 * y - 7 * (y + (m + 9) // 12) // 4 + 275 * m // 9
a += d - 730530 + h / 24
return a

Java conversion

public double degress(double rads)
{
    return (rads/PI)*180;
}

public double radians(double degrees)
{
    return (degrees/180 * PI);
}

public double fnday(int y, int m, int d, int h)
{
    double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;
    a += d - 730530 + h / 24;
    return a;
}

I know it may be a simple answer but I need to know the postion of the moon and sun for the app and do not want to rely on an api for this data. I simple want to put in the latitude and longitdue and get the sun and moon rise and set times.

1
  • 1
    Using an API like mine (Time4J) would be much easier and enables good precision (fine agreement with official USNO-data) and offers easy transformation of results to java.time-types. On Android, you can use Time4A. Commented Jan 29, 2018 at 12:53

2 Answers 2

3

Using a double for each variable would suffice; however, you have an issue that results from integer division:

double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;

If I were you, I'd change y, m, d, and h to all be doubles, so you retain the decimal places when dividing:

public double fnday(double y, double m, double d, double h) {
    double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;

    a += d - 730530 + h / 24;

    return a;
}
Sign up to request clarification or add additional context in comments.

1 Comment

missed that. I will make that change. Appreciate the info.
0

If you need a really big precision, the best way is use, java.lang.BigDecimal, that extends from java.math.Number.

You can even use your existing doubles if you need:

double d = 67.67;
BigDecimal bd = new BigDecimal(d);

But you will need to use the methods from the class like this:

public BigDecimal degress(BigDecimal rads)
{
    BigDecimal pi = new BigDecimal(PI);
    return (rads.divide(pi))*180;
}

6 Comments

Given I only need accuracy to within 5 minutes do you think I should use BigDecimal instead of double as I am at the start of the conversion process?
@timv It's sure to be much more accurate, I can't figure out how much precision do you need, but if I were you, and I'm looking for more precision, I would use that. Be careful be cause if you initialize BigDecimal with doubles you drag with it the precision, look it also stackoverflow.com/questions/9795364/…
Funny to suggest to use BigDecimal to then use it with its deprecated double constructor.
Maybe I can keep them as doubles during the conversion, run some tests with a few locations (lats, lngs) and then test again replacing the doubles with BigDecimals. I will then answer my question with my findings.
Fantastic! @timv Let me know how it worked for you :D
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.