Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Nov 13, 2010, 11:48 AM   #1
gotenks05
macrumors member
 
Join Date: Jan 2009
[Java] RMD Calculations Always come out to zero

I am trying to work on an Android app, but I am having troubles. The program calculates the age of the person depending on their birth date and current date, then figure the RMD value. The program is accepting the birth date and the balance, because those show up fine, but the RMD value always comes to zero. Now, before you guys go saying "Go somewhere else. We don't deal with Android programming", I have verified that this is a problem in J2SE as well. The age and RMD values are calculated in an external class and when I tested out the external class with a desktop program, it gives me the same results as the Android app, which means the problem is definitely in my external class and it is a Java problem, not an Android platform exclusive problem. How do I fix this, so that the RMD shows the correct results, instead of "0.0"?

Here is the external class source:

Code:
import java.util.*;
import java.text.*;

public class RMD
{
	double balance;
	double rmd;
	long age;
	String bdate;
	SimpleDateFormat sd = new SimpleDateFormat("MM/dd/yyyy");
	
	Date current = new Date();
	public void setBalance(double i)
	{
		balance = i;
	}

	public double getBalance()
	{
		return balance;
	}

	public void setBDate(String h)
	{
		bdate = h;
	}

	public long getAge() throws Exception
	{
		
		Date birthd = sd.parse(bdate);
		long cur;
		long birth;
		long diff;

		cur = current.getTime();
		birth = birthd.getTime();
		diff = cur - birth;
		age = (diff/(24*60*60*1000))/365;
		return age;
	}

	public double getRMD()
	{

		if (age == 70)
		{
			rmd = balance/27.4;
		}

		if (age == 71)
		{
			rmd = balance/26.5;
		}

		if (age == 72)
		{
			rmd = balance/25.6;
		}

		if (age == 73)
		{
			rmd = balance/24.7;
		}

		if (age == 74)
		{
			rmd = balance/23.8;
		}

		return rmd;
	}
}
Yes, I have tried the equals and the compareTo() methods. They either returned the same results or complained that I was trying to dereference a long variable.
gotenks05 is offline   0 Reply With Quote
Old Nov 13, 2010, 01:07 PM   #2
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
it appears that the variable "rmd" is only calculated if the age is 70, 71, 72, 73, or 74. Otherwise it is always returned as 0.0 (the starting value).

EDIT: also, the age thing (meaning the multiple if statements) is horrible programming in general. Though I guess if there is really no formula for the conversion you'll be stuck with something similar. But at least use a switch control structure.
jared_kipe is offline   0 Reply With Quote
Old Nov 13, 2010, 01:17 PM   #3
gotenks05
Thread Starter
macrumors member
 
Join Date: Jan 2009
Quote:
Originally Posted by jared_kipe View Post
it appears that the variable "rmd" is only calculated if the age is 70, 71, 72, 73, or 74. Otherwise it is always returned as 0.0 (the starting value).

EDIT: also, the age thing (meaning the multiple if statements) is horrible programming in general. Though I guess if there is really no formula for the conversion you'll be stuck with something similar. But at least use a switch control structure.
I'll try the switch statement. As for the formula, it depends on the age since there are certain values that the balance must be divided by, as provided by online RMD tables.

Update: I have now implemented a switch control structure the code now looks like this:

Code:
import java.util.*;
import java.text.*;

public class RMD
{
	double balance;
	double rmd;
	long age;
	String bdate;
	SimpleDateFormat sd = new SimpleDateFormat("MM/dd/yyyy");
	
	Date current = new Date();
	public void setBalance(double i)
	{
		balance = i;
	}

	public double getBalance()
	{
		return balance;
	}

	public void setBDate(String h)
	{
		bdate = h;
	}

	public long getAge() throws Exception
	{
		
		Date birthd = sd.parse(bdate);
		long cur;
		long birth;
		long diff;

		cur = current.getTime();
		birth = birthd.getTime();
		diff = cur - birth;
		age = (diff/(24*60*60*1000))/365;
		return age;
	}

	public double getRMD()
	{
		int years = (int)age;

		switch (years)
		{
			case 70: rmd = balance/27.4; break;

			case 71: rmd = balance/26.5; break;

			case 72: rmd = balance/25.6; break;

			case 73: rmd = balance/24.7; break;

			case 74: rmd = balance/23.8; break;
			default: rmd = 0.0; break;
		}

		return rmd;
	}
}
It still gives the same trouble, but this might be better code to read.

Update 2: I found a solution, although it is not exactly what I wanted. I would have like to keep the single method solution, but it did not work out as well as separating the formulas into separate methods for each age. If anyone can provide a solution to that, I'd be grateful.

Last edited by gotenks05; Nov 13, 2010 at 02:02 PM. Reason: solution found
gotenks05 is offline   0 Reply With Quote
Old Nov 13, 2010, 02:45 PM   #4
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
I have no idea what you're talking about. Why is age stored as a long and then cast to an integer "years"?

Why are you only testing these few select years?

Why not put
int years = getAge();
into the getRMD method, since getAge calculates the age itself.
jared_kipe is offline   0 Reply With Quote
Old Nov 13, 2010, 04:17 PM   #5
gotenks05
Thread Starter
macrumors member
 
Join Date: Jan 2009
Quote:
Originally Posted by jared_kipe View Post
I have no idea what you're talking about. Why is age stored as a long and then cast to an integer "years"?

Why are you only testing these few select years?

Why not put
int years = getAge();
into the getRMD method, since getAge calculates the age itself.
I did it that way since the switch statement only accepts integers. Also, I was only able to use either a long or a double in calculating the age, unless the millisecond values of the dates can be held in an integer, so the age would need to be cast as an integer anyway, since both a double and a long are larger values than an integer.

Also, I was only testing those years, since those were the only ages I had on hand at the time. I looked up the info for all of the other ages and have those, but if the method does not work with that small group, how would it even work with ages 75-115+. Values end at age 115, so everyone older than 115 gets treated like they are 115.

Update: I found the solution. From the information provided by jared_kipe, I used this:

Code:
switch ((int)getAge())
and everything worked.

Last edited by gotenks05; Nov 13, 2010 at 05:02 PM. Reason: found the solution
gotenks05 is offline   0 Reply With Quote
Old Nov 13, 2010, 05:36 PM   #6
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
Quote:
Originally Posted by gotenks05 View Post
I did it that way since the switch statement only accepts integers. Also, I was only able to use either a long or a double in calculating the age, unless the millisecond values of the dates can be held in an integer, so the age would need to be cast as an integer anyway, since both a double and a long are larger values than an integer.
Umm so they are 70-75 milliseconds old?? Obviously you are NOT storing milliseconds in the age variable so there is no need for it to be a long type.

You do realize why that worked right? The method getAge() is somewhat poorly named as it actually calculates it (and calculates it every time...).

Also, normally getters/setters are named as such:
age()
setAge()
jared_kipe is offline   0 Reply With Quote
Old Nov 13, 2010, 07:44 PM   #7
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Some notes:
If you want the birthdate as a date, just store it as one. It's wasteful to parse it every time getAge is called.
getAge sets an ivar, but does so every time it's called. Either calculate the age whenever the birthdate is set, and just return it when getAge is called, or get rid of the age ivar, make it local, and rename getAge to calculateAge.
getAge does not get the age in years. Dividing days old by 365 does not give you years old.
I would find another way to grab the denominator for RMD by age in years. Maybe a sparse array, maybe an array with an easily calculated index that you wrap in a function, maybe a Hash, etc. Using a switch here is overkill, and makes adding or changing these values more difficult than it needs to be.
Your current date is initialized when your object is instantiated. If the object lives for a few days your calculations will no longer be current.
Your rmd ivar is like your age ivar. Calculate when you have birthdate and balance available and just return this or rename the method calculateRMD and make the ivar local.

-Lee
lee1210 is online now   0 Reply With Quote
Old Nov 14, 2010, 08:56 AM   #8
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
Based on the hand typed constants, the denominator is (90.4 - 0.9*(ageInYears))
jared_kipe is offline   0 Reply With Quote
Old Nov 14, 2010, 12:06 PM   #9
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by jared_kipe View Post
Based on the hand typed constants, the denominator is (90.4 - 0.9*(ageInYears))
Guessing that RMD means "Required Minimum Distribution" regarding an IRA (Independent Retirement Account), I strongly suggest using the IRS-supplied tables and procedures, rather than calculating a figure:
http://www.irs.gov/retirement/articl...=96989,00.html

One of the problems appears to be that the OP doesn't know how to make or use tables. Another problem is that some things are not simply a calculation based on age, but on the year in which one attains a specified age. Furthermore, the specified age is fractional (e.g. 70.5), so a long or int type is unlikely to work correctly.

If this isn't regarding Required Minimum Distributions from an IRA, then ignore the above.
chown33 is offline   0 Reply With Quote
Old Nov 14, 2010, 04:16 PM   #10
gotenks05
Thread Starter
macrumors member
 
Join Date: Jan 2009
Quote:
Originally Posted by jared_kipe View Post
Umm so they are 70-75 milliseconds old?? Obviously you are NOT storing milliseconds in the age variable so there is no need for it to be a long type.

You do realize why that worked right? The method getAge() is somewhat poorly named as it actually calculates it (and calculates it every time...).

Also, normally getters/setters are named as such:
age()
setAge()
Wrong. If you look at this:

Code:
cur = current.getTime();
		birth = birthd.getTime();
		diff = cur - birth;
The dates are in milliseconds, because that is the only way I could find the difference between the two dates with the java.util.Date class. From there, I have to convert it into years by using this:

Code:
age = (diff/(24*60*60*1000))/365;
I could cast that line as an integer, but that does not mean I can take the millisecond value of the current date and the date of birth and make them integers.


Quote:
Originally Posted by lee1210 View Post
Some notes:
If you want the birthdate as a date, just store it as one. It's wasteful to parse it every time getAge is called.
getAge sets an ivar, but does so every time it's called. Either calculate the age whenever the birthdate is set, and just return it when getAge is called, or get rid of the age ivar, make it local, and rename getAge to calculateAge.
getAge does not get the age in years. Dividing days old by 365 does not give you years old.
I would find another way to grab the denominator for RMD by age in years. Maybe a sparse array, maybe an array with an easily calculated index that you wrap in a function, maybe a Hash, etc. Using a switch here is overkill, and makes adding or changing these values more difficult than it needs to be.
Your current date is initialized when your object is instantiated. If the object lives for a few days your calculations will no longer be current.
Your rmd ivar is like your age ivar. Calculate when you have birthdate and balance available and just return this or rename the method calculateRMD and make the ivar local.

-Lee
The only database I can use with Android is SQLite, since the application does not access the web. Besides, I'm not coding this in PHP, or I could use MySQL, which I more familiar with than SQLite. Also the birth date is entered by the user. All user input in GUI, at least in Java can only be obtained as a String, thus required me to parse as a date. I could have stored it as a date, if I used a combo of PHP+MySQL.

Quote:
Originally Posted by chown33 View Post
Guessing that RMD means "Required Minimum Distribution" regarding an IRA (Independent Retirement Account), I strongly suggest using the IRS-supplied tables and procedures, rather than calculating a figure:
http://www.irs.gov/retirement/articl...=96989,00.html

One of the problems appears to be that the OP doesn't know how to make or use tables. Another problem is that some things are not simply a calculation based on age, but on the year in which one attains a specified age. Furthermore, the specified age is fractional (e.g. 70.5), so a long or int type is unlikely to work correctly.

If this isn't regarding Required Minimum Distributions from an IRA, then ignore the above.
Yes, the person that wanted me to make the application did say that, but the formula still depends on getting the person's age, since the divisor changes according to age. I got the formula from an accountant. Also, all RMD tables start at age 70, even though the specified age is 70.5, as you say. Creating tables in Android is different from normal Java, so even if I did try to make or load a table it would take a bit more research between the Android and J2SE APIs. This thread was to deal with the calculation, which is dealing with a class that can be used on Android and J2SE, which I finally found the solution.
gotenks05 is offline   0 Reply With Quote
Old Nov 14, 2010, 05:25 PM   #11
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
Quote:
Originally Posted by gotenks05 View Post
Wrong. If you look at this:

Code:
cur = current.getTime();
		birth = birthd.getTime();
		diff = cur - birth;
The dates are in milliseconds, because that is the only way I could find the difference between the two dates with the java.util.Date class. From there, I have to convert it into years by using this:

Code:
age = (diff/(24*60*60*1000))/365;
I could cast that line as an integer, but that does not mean I can take the millisecond value of the current date and the date of birth and make them integers.
Wrong, it is called sarcasm.

You are not storing milliseconds in age, there is no chance of overflow.
jared_kipe is offline   0 Reply With Quote
Old Nov 14, 2010, 05:56 PM   #12
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by gotenks05 View Post
Yes, the person that wanted me to make the application did say that, but the formula still depends on getting the person's age, since the divisor changes according to age. I got the formula from an accountant. Also, all RMD tables start at age 70, even though the specified age is 70.5, as you say.
FWIW, your calculation of age is wrong. There aren't exactly 365 days in a year. You haven't accounted for leap years. This will cause errors for people whose birthdays are in early January, or even into later January if of advanced age.

Quote:
Creating tables in Android is different from normal Java, so even if I did try to make or load a table it would take a bit more research between the Android and J2SE APIs.
Different in what way? A simple table would be an array of doubles indexed by the age in years (perhaps offset by -70), and initialized with a static initializer. Are you saying that Android doesn't allow static initializers?

My mention of a table was a design point, in the same way that an earlier suggestion of replacing multiple if's with a switch was also a design point. After the design is table-based, you can change how the table gets loaded, e.g. to read a file instead of using a static initializer. But if all the values are compiled in, as both if and switch require, then you always have to edit and recompile in order to change the values.

Last edited by chown33; Nov 15, 2010 at 10:17 AM. Reason: typos
chown33 is offline   0 Reply With Quote
Old Nov 14, 2010, 07:23 PM   #13
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Quote:
Originally Posted by chown33 View Post
FWIW, your calculation of age is wrong. There aren't exactly 365 days in a year. You haven't accounted for leap years. This will cause errors for people whose birthdays are in early January, or even into later January if of advanced age.
This is one of the six things I mentioned, only one of which the OP addressed, and they did so based on a misunderstanding.

I am afraid that the OP is approaching a (for-pay?) project on very unstable ground. There seems to be programming (or maybe just OOP?) inexperience as well as being unfamiliar with the language, terminology, and platform.

I don't know what android brings to the table, but there are many things wrong here (many I tried to detail) and if this is intended to be used in production I feel for the end user.

To the OP: everyone here is trying to help you and some of your responses have been defensive or combative. Forget about PHP and mySQL. If you don't know enough about Java, its APIs, and your database backend, you should take a few steps back and study these (as well as OOP concepts in general) before diving headlong into a project for a customer. We will be happy to help along the way.

-Lee
lee1210 is online now   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
thread Thread Starter Forum Replies Last Post
MBP configuration comes out to $3400, good deal? Alexjones Buying Tips and Advice 17 May 29, 2010 11:01 PM
Need Help with this... Always Comes out when.. Sdahe iPhone Tips, Help and Troubleshooting 2 Dec 10, 2008 02:21 PM
Question| Does The Sims 3 will come out to MAC also? dornirit Mac and PC Games 2 Sep 28, 2008 07:19 PM
Anyone else have trouble typing "Theyre"? Always comes out as "Theyrr"? TheSpaz iPod touch 5 Mar 10, 2008 02:37 PM
when is halo coming out to the mac? junkionxl Games 13 Feb 27, 2003 08:12 PM


All times are GMT -5. The time now is 12:18 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC