在 Java 中输入天体的坐标和视差时距离错误
Getting wrong distances when entering coordinates and parallaxes for celestial objects in Java
我正在开发一个天文数据库程序,该程序允许用户创建和输入他们自己的恒星和褐矮星等,用于大学的入门级编程课程。每个物体都有确定其在 space 中位置的 xyz 坐标,太阳位于 0, 0, 0 光年。
但是,由于许多星空数据库(例如 SIMBAD)、维基百科等根据视差角和右 ascension/declination 坐标给出天文物体的位置,因此我为用户提供了选项使用这些参数添加对象,以防它们没有 xyz 坐标。不过,我无法让它提供准确的值。
这是输入视差角的代码,可以选择输入 arcseconds/as 和 milliarcseconds/mas:
/**
* Notes:
* scReadIntMM(n1, n2); reads and returns user-entered ints within the range n1 to n2, via Scanner
* scReadDoubleMM(n1, n2); is the same, only for doubles.
*/
//user chooses units for entering parallax
System.out.println("Entering parallax and RA/Dec coordinates.");
System.out.println();
System.out.println("Which units do you wish to use?");
System.out.println("(1) Arcseconds (1 as = 1/3600 degrees)");
System.out.println("(2) Milliarcseconds (1 mas = 1/1000 arcseconds)");
userChoice = scReadIntMM(1, 2); //stores user choice
System.out.println();
//user enters angle, converts to distance and stores
if (userChoice == 1){
//if user chose to enter in arcseconds
System.out.println("Set object's parallax angle, in arcseconds.");
System.out.println("Maximum: 3.26167 (corresponding to a distance of exactly 1 light year)");
System.out.println("Minimum: 0.006523266 (corresponding to a distance of about 500 light years)");
dist = (3.26167 / (scReadDoubleMM(0.006523266, 3.26167)));
System.out.println();
} else if (userChoice == 2){
//if user chose to enter in milliarcseconds
System.out.println("Set object's parallax angle, in milliarcseconds.");
System.out.println("Maximum: 3261.67 (corresponding to a distance of exactly 1 light year)");
System.out.println("Minimum: 6.523266 (corresponding to a distance of about 500 light years)");
dist = (3.26167 / ((scReadDoubleMM(6.523266, 3261.67)) / 1000));
System.out.println();
}
当我在计算后添加一个额外的 println 语句来检查 dist 的值时,这两个都给出了正确的结果(即 3.26167 / (angle in as)
)。例如,输入 Sirius' parallax (0.37921 as, 379.21 mas 给出 8.60 光年的值,这正是我在查看其维基百科页面后所期望看到的。
下一阶段似乎一切都出了问题。这部分是用户输入坐标的地方,使用 this site 中列出的过程将其转换为度数,然后在输入所有内容后更改为弧度:
//user enters right ascension
System.out.println("Enter hours of right ascension. (Must be between 0 and 23, whole");
System.out.println("numbers only.)");
ra = (((double)scReadIntMM(0, 23)) * 15.0); //enters hours
System.out.println();
System.out.println("Enter minutes of right ascension. (Must be between 0 and 59, whole");
System.out.println("numbers only.)");
ra = ra + (((double)scReadIntMM(0, 59) / 60.0) * 15.0); //enters mins
System.out.println();
System.out.println("Enter seconds of right ascension. (Must be between 0 and 59.999999.)");
ra = ra + ((scReadDoubleMM(0, 59.999999) / 3600.0) * 15.0); //enters secs
ra = Math.toRadians(ra); //converts from degrees to radians
System.out.println();
//user enters sign for declination (+ or -)
System.out.println("Is the object's declination positive or negative? (Enter a number.)");
System.out.println("(1) Positive");
System.out.println("(2) Negative");
userChoice = scReadIntMM(1, 2); //stores dec sign
System.out.println();
//user enters declination
System.out.println("Enter degrees of declination, without positive or negative signs. (Must be");
System.out.println("between 0 and 90, whole numbers only.)");
dec = ((double)scReadIntMM(0, 90)); //enter degrees
System.out.println();
System.out.println("Enter minutes of declination. (Must be between 0 and 59, whole");
System.out.println("numbers only.)");
dec = dec + (((double)scReadIntMM(0, 59)) / 60.0); //enter mins
System.out.println();
System.out.println("Enter seconds of declination. (Must be between 0 and 59.999999.)");
dec = dec + (scReadDoubleMM(0, 59.999999) / 3600.0); //enter secs
dec = dec * userChoice; //sets declination sign
dec = Math.toRadians(dec); //converts from degrees to radians
System.out.println();
然后,RA/Dec 值用于计算 x、y、z 值,仍然按照我之前链接到的页面上的说明进行操作:
//calculates x, y, z coords from ra/dec and distance values
xIn = ((dist * Math.cos(dec)) * Math.cos(ra));
yIn = ((dist * Math.cos(dec)) * Math.cos(ra));
zIn = (dist * Math.sin(dec));
使用这种方法,我得到的天狼星距离为 5.139 光年(使用维基百科上列出的视差和 RA/Dec),而不是仅使用视差计算的 8.60 光年值。我也低估了更远的东西,比如一个应该在 ~388 ly 之外的物体更近了几十 ly。
虽然我真的看不出任何可能出错的地方。我唯一能想到的是在为 RA/Dec 输入 H/M 或 D/M 时 int 值覆盖双精度值,我很早就修复了这个问题(它导致了更大的错误)。我在这里缺少什么吗?也许只是由于使用双打而不是多头造成的损失。
从你发的link看来,yIn应该是:
((dist * Math.cos(dec)) * Math.sin(ra));
而不是
((dist * Math.cos(dec)) * Math.cos(ra));
我正在开发一个天文数据库程序,该程序允许用户创建和输入他们自己的恒星和褐矮星等,用于大学的入门级编程课程。每个物体都有确定其在 space 中位置的 xyz 坐标,太阳位于 0, 0, 0 光年。
但是,由于许多星空数据库(例如 SIMBAD)、维基百科等根据视差角和右 ascension/declination 坐标给出天文物体的位置,因此我为用户提供了选项使用这些参数添加对象,以防它们没有 xyz 坐标。不过,我无法让它提供准确的值。
这是输入视差角的代码,可以选择输入 arcseconds/as 和 milliarcseconds/mas:
/**
* Notes:
* scReadIntMM(n1, n2); reads and returns user-entered ints within the range n1 to n2, via Scanner
* scReadDoubleMM(n1, n2); is the same, only for doubles.
*/
//user chooses units for entering parallax
System.out.println("Entering parallax and RA/Dec coordinates.");
System.out.println();
System.out.println("Which units do you wish to use?");
System.out.println("(1) Arcseconds (1 as = 1/3600 degrees)");
System.out.println("(2) Milliarcseconds (1 mas = 1/1000 arcseconds)");
userChoice = scReadIntMM(1, 2); //stores user choice
System.out.println();
//user enters angle, converts to distance and stores
if (userChoice == 1){
//if user chose to enter in arcseconds
System.out.println("Set object's parallax angle, in arcseconds.");
System.out.println("Maximum: 3.26167 (corresponding to a distance of exactly 1 light year)");
System.out.println("Minimum: 0.006523266 (corresponding to a distance of about 500 light years)");
dist = (3.26167 / (scReadDoubleMM(0.006523266, 3.26167)));
System.out.println();
} else if (userChoice == 2){
//if user chose to enter in milliarcseconds
System.out.println("Set object's parallax angle, in milliarcseconds.");
System.out.println("Maximum: 3261.67 (corresponding to a distance of exactly 1 light year)");
System.out.println("Minimum: 6.523266 (corresponding to a distance of about 500 light years)");
dist = (3.26167 / ((scReadDoubleMM(6.523266, 3261.67)) / 1000));
System.out.println();
}
当我在计算后添加一个额外的 println 语句来检查 dist 的值时,这两个都给出了正确的结果(即 3.26167 / (angle in as)
)。例如,输入 Sirius' parallax (0.37921 as, 379.21 mas 给出 8.60 光年的值,这正是我在查看其维基百科页面后所期望看到的。
下一阶段似乎一切都出了问题。这部分是用户输入坐标的地方,使用 this site 中列出的过程将其转换为度数,然后在输入所有内容后更改为弧度:
//user enters right ascension
System.out.println("Enter hours of right ascension. (Must be between 0 and 23, whole");
System.out.println("numbers only.)");
ra = (((double)scReadIntMM(0, 23)) * 15.0); //enters hours
System.out.println();
System.out.println("Enter minutes of right ascension. (Must be between 0 and 59, whole");
System.out.println("numbers only.)");
ra = ra + (((double)scReadIntMM(0, 59) / 60.0) * 15.0); //enters mins
System.out.println();
System.out.println("Enter seconds of right ascension. (Must be between 0 and 59.999999.)");
ra = ra + ((scReadDoubleMM(0, 59.999999) / 3600.0) * 15.0); //enters secs
ra = Math.toRadians(ra); //converts from degrees to radians
System.out.println();
//user enters sign for declination (+ or -)
System.out.println("Is the object's declination positive or negative? (Enter a number.)");
System.out.println("(1) Positive");
System.out.println("(2) Negative");
userChoice = scReadIntMM(1, 2); //stores dec sign
System.out.println();
//user enters declination
System.out.println("Enter degrees of declination, without positive or negative signs. (Must be");
System.out.println("between 0 and 90, whole numbers only.)");
dec = ((double)scReadIntMM(0, 90)); //enter degrees
System.out.println();
System.out.println("Enter minutes of declination. (Must be between 0 and 59, whole");
System.out.println("numbers only.)");
dec = dec + (((double)scReadIntMM(0, 59)) / 60.0); //enter mins
System.out.println();
System.out.println("Enter seconds of declination. (Must be between 0 and 59.999999.)");
dec = dec + (scReadDoubleMM(0, 59.999999) / 3600.0); //enter secs
dec = dec * userChoice; //sets declination sign
dec = Math.toRadians(dec); //converts from degrees to radians
System.out.println();
然后,RA/Dec 值用于计算 x、y、z 值,仍然按照我之前链接到的页面上的说明进行操作:
//calculates x, y, z coords from ra/dec and distance values
xIn = ((dist * Math.cos(dec)) * Math.cos(ra));
yIn = ((dist * Math.cos(dec)) * Math.cos(ra));
zIn = (dist * Math.sin(dec));
使用这种方法,我得到的天狼星距离为 5.139 光年(使用维基百科上列出的视差和 RA/Dec),而不是仅使用视差计算的 8.60 光年值。我也低估了更远的东西,比如一个应该在 ~388 ly 之外的物体更近了几十 ly。
虽然我真的看不出任何可能出错的地方。我唯一能想到的是在为 RA/Dec 输入 H/M 或 D/M 时 int 值覆盖双精度值,我很早就修复了这个问题(它导致了更大的错误)。我在这里缺少什么吗?也许只是由于使用双打而不是多头造成的损失。
从你发的link看来,yIn应该是:
((dist * Math.cos(dec)) * Math.sin(ra));
而不是
((dist * Math.cos(dec)) * Math.cos(ra));