在模拟时钟中,找到时针和分针之间的夹角。

34
我最近得到了这个面试问题:
给定一个12小时制的模拟时钟,计算时针和分针之间的较小角度。尽可能精确。
我想知道最简单、最易读、最精确的算法是什么。欢迎使用任何语言的解决方案(但如果您认为有必要,请进行解释)。

9
最简单的方法?在维基百科上查找!:http://en.wikipedia.org/wiki/Clock_angle_problem - Mitch Wheat
4
我认为这是一个纯数学问题,而且相当简单。我不明白这个问题如何能得到四个赞... - Andreas Rejbrand
10个回答

44

结果发现维基百科确实给出了最好的答案:

// h = 1..12, m = 0..59
static double angle(int h, int m) {
    double hAngle = 0.5D * (h * 60 + m);
    double mAngle = 6 * m;
    double angle = Math.abs(hAngle - mAngle);
    angle = Math.min(angle, 360 - angle);
    return angle;
}

基本上:

  • 时针每分钟移动 0.5
  • 分针每分钟移动 6

问题解决了。


而且精度不是问题,因为小数部分只有 .0 或者 .5,在 0..360 的范围内,所有这些值在 double 中都可以精确表示。


1
@starblue: 我已经澄清它是一个12小时的模拟时钟。 - polygenelubricants
17
模拟时钟可以是24小时制吗? - AksharRoop
为什么是30/60=0.5D?而不是330/60=5.5D? - SMUsamaShah
@starblue 只需执行 hour%12 就可以了。 - Pubudu Perera
12:15不是90度角吗?如果时钟是一个完美的圆,指向12的针应该与3形成90度角,不是吗? - DjangoBlockchain
那是因为15分钟过去的时候,时针已经移动了四分之一到1点钟的位置。 - Julix

8

要计算时钟指针之间的夹角,

30 * [HRS - (MIN/5)] + (MIN/2) 

缺少绝对值? - Hunter McMillen
请解释5和2的值。描述这两个值的计算方式以及它们来自哪里。 - vivek

6

这段Java代码与我的代码相似。假设时钟是12小时制而非24小时制。

如果是24小时制,则情况不同。还有一个假设,即在计算过程中停止时钟。

一个时钟周期为360度。

  1. 每分钟指针可以转多少度?360/60=6度每分钟。

  2. 每小时指针可以转多少度?360/12=30度每小时(因为指针转动速度比分针慢)

由于用“分钟”单位更容易计算,让我们来计算

“每分钟时针可以转多少度”?

30 / 60 = 0.5度每分钟。

因此,如果您知道如何获得这些数字,这个问题几乎可以通过这个部分的数学解决方案解决。


1
    **php code for find angle via time (minutes and hour's)**

    echo calcAngle(3,70);

function calcAngle($h, $m)
{
    // validate the input
    if ($h <0 || $m < 0 || $h >12 || $m > 60)
      {
       return "Wrong input";
      }
      else {

    if ($h == 12) $h = 0;
    if ($m == 60) $m = 0;

    $hour_angle = 0.5 * ($h*60 + $m);
    $minute_angle = 6*$m;
    $angle = abs($hour_angle - $minute_angle);
    $angle = min(360-$angle, $angle);

    return $angle;
}
}

1

尝试这段代码:

import java.util.Scanner;

class Clock{

    public static void main(String args[]){
        int hours,mins;

    System.out.println("Enter the Time(hours) : ");
        Scanner dx = new Scanner(System.in);
        hours = dx.nextInt();

    System.out.println("Enter the time(mins) : ");
        Scanner fx = new Scanner(System.in);
        mins = fx.nextInt();

    if(hours>=0 && hours<=12){

        if(mins>=0 && mins<=59){
            double hDegrees = (hours * 30) + (mins * 0.5);
                    double mDegrees = mins * 6;
                    double diff  = Math.abs(hDegrees - mDegrees);

        System.out.println("The angle between sticks is (degrees) : "+diff);
                if (diff > 180){ 

                diff = 360 - diff;
        System.out.println("The angle between sticks is (degrees) : "+diff);
                }

        }

    }

    else{
        System.out.println("Wrong input ");
    }


}

}

1

分钟角度(从12点钟开始):360 * 分钟数 / 60

小时角度(从12点钟开始):360 * (小时数 % 12) / 12 + 360 * (分钟数 / 60) * (1 / 12)

小时和分钟之间的夹角:(小时角度 - 分钟角度) % 360,通过简单的算术运算,可以将其简化为30 * 小时数 - 5.5 * 分钟数。


0
问题被称为“时钟角问题”,我们需要找到模拟时钟上的指针(时针和分针)在特定时间之间的夹角。
C编程语言中的解决方案。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<inttypes.h>
#include<assert.h>

#define STRING_LENGTH 6

double angle_between_hour_min_hand(char[]);

int main(void) {
    uint8_t test;
    printf("Enter the number of test cases\n");
    scanf("%"SCNu8,&test);
    assert(test>0);
    while(test--) {
        char time_digital[STRING_LENGTH];
        printf("Enter the time\n");
        scanf("%s",time_digital);
        double angle_between_hands_deg = angle_between_hour_min_hand(time_digital);
        abs(angle_between_hands_deg) < angle_between_hands_deg ? printf("%0.1f\n",angle_between_hands_deg) : printf("%d\n",abs(angle_between_hands_deg));
    }
    return 0;
}

double angle_between_hour_min_hand(char time_digital[]) {
    uint8_t hr,min;
    double hr_angle_deg,min_angle_deg,angle_between_hands_deg;
    char*buffer = calloc(sizeof(char),STRING_LENGTH);
    if(buffer) {
        snprintf(buffer,STRING_LENGTH,"%s",time_digital);
        hr = atoi(__strtok_r(buffer,":",&buffer));
        min = atoi(__strtok_r(NULL,":",&buffer));
        buffer -= strlen(time_digital);
        free(buffer);
        hr_angle_deg = (double)(30*hr) + (double) (0.5*min);
        // printf("hr-angle: %f\n", hr_angle_deg);
        min_angle_deg = 6*min;
        // printf("min-angle: %f\n", min_angle_deg);
        angle_between_hands_deg = (hr_angle_deg > min_angle_deg) ? hr_angle_deg - min_angle_deg : min_angle_deg - hr_angle_deg;
        if(angle_between_hands_deg > 180) {
            angle_between_hands_deg = 360 - angle_between_hands_deg;
        }
    }
    else fprintf(stderr,"Memory not allocated to the buffer pointer!\n");
    return angle_between_hands_deg;
}

在您的系统中编译上述程序,我使用了Ubuntu 18.04 LTS Bionic Beaver,您可以使用任何已安装C编译器的系统。

gcc -Wall -g clock_angle_sol.c -o clock_angle_sol
./clock_angle_sol
Enter the time in 12-hour or 24 hour i.e (hr:min) format: 12:45
Angle: 112.00 degrees.

注意:
1. 方程式$\theta_{hr} = (30^\circ \times hour) + (0.5^\circ \times minute)$将给出12小时制时钟中时针的角度。
2. 如果您想计算24小时制时钟中时针的角度,则使用以下方程式:$\theta_{hr} = (15^\circ \times hour) + (0.25^\circ \times minute)$
3. 秒针也会对分针的旋转产生影响,但我们忽略了它,因为其贡献微不足道,即1/10=0.1。


-1

这是一个解决方案(C#)。这是一个非常简单的解决方案,忽略了精度。希望这个解决方案是自我解释的。

public static double GetAngle(int hourHand, int minuteHand)
    {
        double oneMinuteAngle = (360 / 60);
        double oneHourAngle = (360 / 12);

        double hourAngle = oneHourAngle * hourHand;
        double minuteAngle = oneMinuteAngle * minuteHand;

        return (Math.Abs(hourAngle - minuteAngle));
    }

这个答案是错误的。在1:30时,时针正好在1和2之间的中间位置... - Nemo

-3
找到时针和分针之间的角度是
angle=(hour*5-min)*6

这个答案有什么问题? - user6123723

-3

我不知道这是否正确,大概是这样吧?

//m*360/60 - (h*360/24)+(m*360/(24*60)) ->
t = abs(25*m - 60*h)/4
t = min(t,360-t)

如果你缺少一个右括号,那么它肯定是不正确的 :D - Ponkadoodle
对于 h=3m=0,我得到了 45。应该是 90 - polygenelubricants
@poly 好的,我忘了普通时钟是12小时制而不是24小时制。如果你将除以24的部分替换为12,那么你应该会得到正确的结果。 - Anycorn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接