【问题标题】:C: Converting Julian Dates into GregorianC: 将儒略历转换为公历
【发布时间】:2014-11-27 17:44:49
【问题描述】:

这是我当前的代码,输出如下:

请输入一个大于 2299160 的儒略日数

2299161

15 10 1582

但是,如果有小数点 2299161.1 等,这并不能提供确切的时间。

这将如何在 C 中实现?我已经知道数学了:

0.1 days = 0.1 * 24 hours   = 2 hours    (remainder 0.4 hours),
       0.4 * 60 minutes = 24 minutes (remainder 0.0 seconds)
       0.0 * 60 seconds = 0 seconds

#include <stdio.h>

int main( ) {
   double jdn; /* you will need to store the user's input here... */
   long lc, kc, nc, ic, jc;
   int day, month, year;
   printf("Please Enter a Julian Day number greater than 2299160 \n");
   scanf("%lf",&jdn);


 if( jdn > 2299160 ){
   printf("%d\n",jdn);
   lc = jdn + 68569;
   nc = ((4 * lc) / 146097);
   lc = lc - ((146097 * nc + 3) / 4);
   ic = ((4000 * (lc + 1)) / 1461001);
   lc = lc - ((1461 * ic) / 4) + 31;
   jc = ((80 * lc) / 2447);
   day = lc - ((2447 * jc) / 80);
   lc = (jc / 11);
   month = jc + 2 - 12 * lc;
   year = 100 * (nc - 49) + ic + lc;

   printf("%d %d %d\n", day, month, year);
  }
  else {
  printf("Invalid number");
}
 return 0;
}

【问题讨论】:

    标签: c matrix converter


    【解决方案1】:

    推荐@Paul R 使用的floor()、@user3386109 使用的整数% 和* 以及round() 的组合。

    #include <math.h>
    
    double frac_d = jdn - floor(jdn);  // @Paul R
    
    #define SecPerDay (24L*60*60)
    long  frac_l = (long) round(frac_d * SecPerDay);
    
    int sec = frac_l % 60;  // @user3386109
    frac_l /= 60;
    int min = frac_l % 60;
    frac_l /= 60;
    int hrs = total;
    

    如果出现负儒略日期时间,使用 floor() 与 modf() 很重要。

    在分配给整数之前将双精度数舍入可确保像 12.99999999 这样的值采用整数值 13 而不是 12。

    出于可移植性原因,对于可能超过 32767 的值,首选 long 而不是 int。


    [编辑]

    我对以下陈述的担忧并未得到证实。计算h,m,s 的任何一种方法都可以很好地得到一致 值。仍然更喜欢整数方法,因为代码更少,更容易控制舍入。

    “从一个整数计算 h,m,s 可以确保分数的值一致。” (无效)

    【讨论】:

      【解决方案2】:

      你可以像这样取小数部分:

      #include <math.h>
      
      double jdn_frac = jdn - floor(jdn);
      

      然后将其转换为 h:m:s:

      非常简单
      int h = (int)(jdn_frac * 24.0);
      int m = (int)((jdn_frac * 24.0 - h) * 60.0);
      int s = (int)(((jdn_frac * 24.0 - h) * 60.0 - m) * 60.0);
      

      LIVE DEMO

      【讨论】:

      • 编译时出错...未定义对“地板”的引用
      • 我不知道你使用的是什么编译器,但是对于 gcc 你可能需要在命令行中添加-lm。
      • 我正在使用 Gcc.. 所以 gcc .c -lm ?
      • 是的,或者更好gcc -Wall -lm foo.c
      【解决方案3】:

      首先将输入数字分成整数和小数部分

      double n, f;
      f = modf( jdn, &n );
      

      这将在f 中为您提供 0.1,在 n 中为您提供 2299161。

      然后将小数部分转换为秒:

      0.1 days = 0.1 * 24 hours = 0.1 * 24 * 3600 seconds
      
      int total = f * 24 * 3600;
      

      然后你可以用模和除法分解它

      seconds = total % 60;
      total /= 60;
      minutes = total % 60;
      total /= 60;
      hours = total;
      

      【讨论】:

      • 我可以编辑而不是 f = modf(2299161.1, &n);使用 f = modf(jdn, &n);
      • 是的,modf 的第一个参数是您想要分成整数和小数部分的数字。所以f=modf(jdn, &amp;n); 会起作用。
      【解决方案4】:

      请注意,以上两篇文章中给出的秒、分和小时将是平均太阳时单位。目前,平均太阳日为 86400.002 秒(http://tycho.usno.navy.mil/leapsec.html)。如果您需要大约 4000 万分之一的精度,则需要对此进行更正。 :-)

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-29
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      相关资源
      最近更新 更多