问题 如何查找时钟的秒针是在更大的区域还是更小的区域[关闭]


我有时间采用以下格式: hh:mm:ss

我必须找到,如果在给定的时间内,秒针位于由时针和分针形成的更大或更小的区域?

我知道时针以每分钟0.5度的速度移动, 分针以每分钟6度的速度移动,秒针以每分钟360度的速度移动。

但我无法找出秒针在哪个区域。那我该怎么做呢?

Second hand within angle between hour and minute hands:
10:15:00
04:40:30

Second hand in reflex angle:
12:01:30

10720
2017-12-14 13:11


起源

简化问题。将时针指向12点。现在画出一些分针固定在某一点的情况。现在弄清楚如何在某个精确的时间计算秒针的位置。完成后,放松分针上的约束。然后放松时针上的约束。但是,除非你有这么远,否则你没有编程问题。 - High Performance Mark
可能重复 确定角度是否位于其他2个角度之间 - fdermishin
你在做什么语言?我提供了一个 C#但是知道这一点会很有帮助,我也假设你到目前为止已经尝试了一些东西,你能展示它以便我们可以帮助你吗? - TheLethalCoder


答案:


这个问题引起了我的兴趣所以我继续写了一个测试项目 C#。据我所知,它必须进行测试才能确定。

这是代码:

string strTime = "10:15:00";

DateTime dt = DateTime.ParseExact(strTime, "HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);

int nHourDegrees = (360 / 12) * dt.Hour;
int nMinuteDegrees = (360 / 60) * dt.Minute;
int nSecondDegrees = (360 / 60) * dt.Second;

if (nHourDegrees > nMinuteDegrees)
{
    int nArea1 = nHourDegrees - nMinuteDegrees;
    int nArea2 = 360 - nArea1;

    bool bArea1IsBigger = (nArea1 >= nArea2);
    if (nSecondDegrees <= nHourDegrees && nSecondDegrees >= nMinuteDegrees)
    {
        //Second hand lies in area1
        if (bArea1IsBigger)
        {
            Console.WriteLine("Second hand is in the larger area");
        }
        else
        {
            Console.WriteLine("Second hand is in the smaller area");
        }
    }
    else
    {
        if (bArea1IsBigger)
        {
            Console.WriteLine("Second hand is in the smaller area");
        }
        else
        {
            Console.WriteLine("Second hand is in the larger area");
        }
    }
}
else if (nMinuteDegrees > nHourDegrees)
{
    int nArea1 = nMinuteDegrees - nHourDegrees;
    int nArea2 = 360 - nArea1;

    bool bArea1IsBigger = (nArea1 >= nArea2);
    if (nSecondDegrees <= nMinuteDegrees && nSecondDegrees >= nHourDegrees)
    {
        //Second hand lies in area1
        if (bArea1IsBigger)
        {
            Console.WriteLine("Second hand is in the larger area");
        }
        else
        {
            Console.WriteLine("Second hand is in the smaller area");
        }
    }
    else
    {
        if (bArea1IsBigger)
        {
            Console.WriteLine("Second hand is in the smaller area");
        }
        else
        {
            Console.WriteLine("Second hand is in the larger area");
        }
    }
}
else
{
    if (nSecondDegrees == nHourDegrees)
    {
        Console.WriteLine("Second hand is on both of the other hands");
    }
    else
    {
        Console.WriteLine("Second hand is in the ONLY area");
    }
}

我们的想法是找到时针和分针之间的区域。然后检查秒针是否在此区域内。我们还将这个区域与另一个区域进行比较,然后我们可以很容易地推断出秒针是否在两者中较小或较大。

注意: 可以对代码进行一些改进:

  1. 它可以明显更短 - 我没有这样做,因为它主要是测试/证明如何做到这一点
  2. 如果超时(即24小时不是12小时),则必须进行改动。即减去12
  3. 如果时间转到12/60/60而不是回到0,则必须手动完成
  4. 可以添加常量以消除对幻数的需要
  5. 与上述类似但常见的计算方式如下 360 / 12 可以移动到常量
  6. 它可以分解为单独的方法以提高可读性
  7. 可以转移到辅助方法,即 bool IsInLargerArea(string timeString)
  8. 当我假设时,需要添加区域大小相同的情况 Area1 如果它们相等则更大,即 >= (大于或等于)
  9. 添加检查以确保只有3个部分 straTimes 排列
  10. 还有一些我没有想过的事情

10
2017-12-14 14:01



一时间说10:15:00。 hourDegree为300,minuteDegree为90,secondDegree为0.上述解决方案如何得到这样的输入结果?我想在那种情况下我们需要另一个条件(secondDegree <= hourDegree && secondDegree <= minuteDegree)|| (secondDegree> = hourDegree && secondDegree> = minuteDegree)。 - poorvankBhatia
@poorvankBhatia在第一个嵌套的if语句之后,一个else语句需要在那里捕获另一个案例,我以为我已经添加了它但是必须忘记了,会编辑 - TheLethalCoder
@poorvankBhatia已经添加了代码来捕获它 - TheLethalCoder
@poorvankBhatia还看到我更改了代码以转换为日期时间对象,因此删除了第10点 - TheLethalCoder


我会选择看起来像这样的方法。你必须确定,如果较小的区域通过0度,然后根据你可以说解决方案。

int minDegree;
int maxDegree;
bool over360;

if (Math.abs(hourHandDegree - minuteHandDegree) < 180){
   minDegree = Math.min(hourHandDegree, minuteHandDegree);
   maxDegree = Math.max(hourHandDegree, minuteHandDegree);
   over360 = false;
} else {
   minDegree = Math.min(hourHandDegree, minuteHandDegree);
   maxDegree = Math.max(hourHandDegree, minuteHandDegree);
   over360 = true;
}

if (over360){
    if ((secondHandDegree < minDegree) && (secondHandDegree > maxDegree)){
        return true;
    } else {
        return false;
    }
} else {
    if ((secondHandDegree > minDegree) && (secondHandDegree < maxDegree)){
        return true;
    } else {
        return false;
    }
}

4
2017-12-14 13:27





该解决方案简洁,易于理解,并允许12小时或24小时输入。

使用弧度时更容易可视化。

以下是 R,但希望很容易阅读。注意 %% 是模运算符。

which_region <- function(s){

  # number of seconds elapsed in day (i.e., since midnight)
  sec <- as.numeric(as.POSIXct(s, tz = "GMT", format = "%H:%M:%S")) %% (12*60*60)

  # angle of each hand, clockwise from vertical, in radians
  hour_ang <- 2*pi * (sec / (12*60*60)) # hour makes a circuit every 12*60*60 sec
  min_ang  <- 2*pi * ((sec / 60^2) %% 1) # min makes a circuit every 60*60 sec 
  sec_ang  <- 2*pi * ((sec / 60) %% 1) # sec makes a circuit every 60 sec

  hour_to_min_ang <- (2*pi + min_ang - hour_ang) %% (2*pi)
  min_to_hr_ang <- (2*pi + hour_ang - min_ang) %% (2*pi)

  if(hour_to_min_ang < min_to_hr_ang){
    return(ifelse(sec_ang > hour_ang & sec_ang < min_ang,
           "Smaller Area","Larger Area") )
  } else if(min_to_hr_ang < hour_to_min_ang){
    return(ifelse(sec_ang > min_ang & sec_ang < hour_ang,
           "Smaller Area","Larger Area") )
  } else return("Equal")
}  

which_region("06:00:00") # Equal
which_region("01:10:00") # Larger Area
which_region("01:20:15") # Smaller Area
which_region("05:10:20") # Smaller Area
which_region("12:00:00") # Equal
which_region("21:55:50") # Smaller Area
which_region("10:55:15 PM") # Larger Area

2
2017-12-14 14:48