儒略历--Java代码(附带发现了一些问题)

题目链接:https://www.luogu.com.cn/problem/P8831

题目描述

在 1582 年之前,以 4 为倍数的年份为闰年。正常情况下,一年中一月到十二月的天数分别是 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 天。如果这年是闰年,那么二月则有 29 天。

但某位教皇发现这么做其实不够准确,会造成误差,因此规定从 1582 年开始,以 4 为倍数的年份,除了以 100 为倍数且不为 400 的倍数年份,才是闰年。同时为了消除误差,规定 1582 年 10 月 4 日的下一天是 1582 年 10 月 15 日,中间的日期就当作不存在了。

现在给出日期,计算这个日期到公元 1 年 1 月 1 日经过的天数。

输入格式

按照 日月年 的格式输入数据,其中日是 1 到 31 之间的整数,月是三个大写字母,年是 1 到 9999 之间的整数。保证这个日期是合法且存在的。

月份的大写字母:

  • 1月:JAN
  • 2月:FEB
  • 3月:MAR
  • 4月:APR
  • 5月:MAY
  • 6月:JUN
  • 7月:JUL
  • 8月:AUG
  • 9月:SEP
  • 10月:OCT
  • 11月:NOV
  • 12月:DEC

输出格式

输出一个整数表示答案

输入输出样例

输入 #1

1JAN1

输出 #1

0

输入 #2

4OCT1582

输出 #2

577736

输入 #3

15OCT1582

输出 #3

577737

输入 #4

21NOV2020

输出 #4

737751

Java代码:

package _传智杯.练习赛;

import java.util.Calendar;
import java.util.Scanner;

public class 儒略历 {
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        String s=sc.next();
        String year=null;
        String month=null;
        String day=null;
        for(int i=0;i<s.length();i++){
            if(!(s.charAt(i)>='0'&&s.charAt(i)<='9')){
                day=s.substring(0,i);
                month=s.substring(i,i+3);
                year=s.substring(i+3);
                break;
            }
        }
        int month1=0;
        int year1=Integer.parseInt(year);
        int day1=Integer.parseInt(day);
        if(month.equals("JAN")) month1=1;
        if(month.equals("FEB")) month1=2;
        if(month.equals("MAR")) month1=3;
        if(month.equals("APR")) month1=4;
        if(month.equals("MAY")) month1=5;
        if(month.equals("JUN")) month1=6;
        if(month.equals("JUL")) month1=7;
        if(month.equals("AUG")) month1=8;
        if(month.equals("SEP")) month1=9;
        if(month.equals("OCT")) month1=10;
        if(month.equals("NOV")) month1=11;
        if(month.equals("DEC")) month1=12;
        Calendar c1=Calendar.getInstance();
        Calendar c2=Calendar.getInstance();
        c1.set(1,0,1);
        c2.set(year1,month1-1,day1);
        long x=c1.getTimeInMillis();
        long y=c2.getTimeInMillis();
        long res=(y-x)/1000/60/60/24;
        System.out.println(res);
    }
}

代码虽然AC,但我发现了一些问题:

Java中Calendar getTimeInMillis()方法返回值存在误差

当我将代码中c1,c2初始化时进行调换,即:

换成 

发现输入相同时输出结果不同:

 仅仅交换次序会造成结果不同?

原来是Java中Calendar getTimeInMillis()方法返回值存在误差,当c1.getTimeInMillis()-c2.getTimeInMillis()得到的两天之间相差的毫秒数并不能十分精确地表示实际相差的毫秒数

以2020年11月21日为例:通过c1.getTimeInMillis()-c2.getTimeInMillis()可得知2020年11月21日到1年1月1日的毫秒数为63741686399998,而实际值应该为63741686400000,一天的毫秒数为86400000,当用63741686399998/86400000时得到737750天,63741686400000/86400000得到737751天

解决方案:

将最终结果进行四舍五入:

换成

最后可保证结果正确

最终代码:

package _传智杯.练习赛;

import java.util.Calendar;
import java.util.Scanner;

public class 儒略历 {
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        String s=sc.next();
        String year=null;
        String month=null;
        String day=null;
        for(int i=0;i<s.length();i++){
            if(!(s.charAt(i)>='0'&&s.charAt(i)<='9')){
                day=s.substring(0,i);
                month=s.substring(i,i+3);
                year=s.substring(i+3);
                break;
            }
        }
        int month1=0;
        int year1=Integer.parseInt(year);
        int day1=Integer.parseInt(day);
        if(month.equals("JAN")) month1=1;
        if(month.equals("FEB")) month1=2;
        if(month.equals("MAR")) month1=3;
        if(month.equals("APR")) month1=4;
        if(month.equals("MAY")) month1=5;
        if(month.equals("JUN")) month1=6;
        if(month.equals("JUL")) month1=7;
        if(month.equals("AUG")) month1=8;
        if(month.equals("SEP")) month1=9;
        if(month.equals("OCT")) month1=10;
        if(month.equals("NOV")) month1=11;
        if(month.equals("DEC")) month1=12;
        Calendar c1=Calendar.getInstance();
        Calendar c2=Calendar.getInstance();
        c1.set(1,0,1);
        c2.set(year1,month1-1,day1);
        long x=c1.getTimeInMillis();
        long y=c2.getTimeInMillis();
        long res= Math.round((y-x)/1000/60/60/24.0);
        System.out.println(res);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值