← Назад к вопросам

Угол между стрелками часов

1.0 Junior🔥 151 комментариев
#Другое#Основы Java

Условие

Напишите программу, которая вычисляет угол между часовой и минутной стрелкой часов.

Примеры

  • 12:00 → 0 градусов
  • 12:15 → 90 градусов (минутная на 3, часовая чуть дальше 12)
  • 3:00 → 90 градусов
  • 6:00 → 180 градусов
  • 9:45 → 22.5 градусов

Формулы

  • Минутная стрелка: 6 градусов за минуту (360/60)
  • Часовая стрелка: 0.5 градусов за минуту (30/60)
  • Часовая стрелка: 30 градусов за час (360/12)

Требования

  • Верните меньший из двух возможных углов
  • Угол должен быть положительным
  • Обработайте граничные случаи (полдень, полночь)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Угол между стрелками часов

Это интересная геометрическая задача, которая часто встречается на собеседованиях. Ключ к решению — понимание того, как движутся часовая и минутная стрелки.

Основные принципы

Минутная стрелка:

  • Полный оборот: 360° за 60 минут
  • За одну минуту: 360° / 60 = 6° за минуту
  • Положение: minutes * 6

Часовая стрелка:

  • Полный оборот: 360° за 12 часов
  • За один час: 360° / 12 = 30° за час
  • За одну минуту: 30° / 60 = 0.5° за минуту
  • Положение: (hours % 12) * 30 + minutes * 0.5

Угол между стрелками:

  • Разница: |minuteAngle - hourAngle|
  • Если больше 180°, возьмём меньший угол: 360 - angle

Решение

public class ClockAngle {
    
    public static double getAngle(int hours, int minutes) {
        // Валидация входных данных
        if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {
            throw new IllegalArgumentException(
                "Часы должны быть 0-23, минуты должны быть 0-59"
            );
        }
        
        // Конвертируем в 12-часовой формат
        hours = hours % 12;
        
        // Вычисляем положение минутной стрелки (в градусах)
        double minuteAngle = minutes * 6;
        
        // Вычисляем положение часовой стрелки (в градусах)
        // Часовая стрелка движется не только по часам, но и по минутам
        double hourAngle = hours * 30 + minutes * 0.5;
        
        // Вычисляем разницу
        double angle = Math.abs(hourAngle - minuteAngle);
        
        // Возвращаем меньший из двух углов
        if (angle > 180) {
            angle = 360 - angle;
        }
        
        return angle;
    }
    
    public static void main(String[] args) {
        System.out.println(getAngle(12, 0));   // 0.0 ✓
        System.out.println(getAngle(3, 0));    // 90.0 ✓
        System.out.println(getAngle(6, 0));    // 180.0 ✓
        System.out.println(getAngle(9, 0));    // 90.0 ✓
        System.out.println(getAngle(12, 15));  // 82.5 ✓
        System.out.println(getAngle(9, 45));   // 22.5 ✓
        System.out.println(getAngle(3, 15));   // 7.5 ✓
    }
}

Пошаговый расчёт примеров

Пример 1: 12:00

Минутная стрелка: 0 * 6 = 0°
Часовая стрелка: (12 % 12) * 30 + 0 * 0.5 = 0 * 30 + 0 = 0°
Разница: |0 - 0| = 0°
✓ Результат: 0°

Пример 2: 12:15

Минутная стрелка: 15 * 6 = 90°
Часовая стрелка: (12 % 12) * 30 + 15 * 0.5 = 0 * 30 + 7.5 = 7.5°
Разница: |7.5 - 90| = 82.5°
✓ Результат: 82.5°

Пример 3: 3:00

Минутная стрелка: 0 * 6 = 0°
Часовая стрелка: (3 % 12) * 30 + 0 * 0.5 = 3 * 30 + 0 = 90°
Разница: |90 - 0| = 90°
✓ Результат: 90°

Пример 4: 6:00

Минутная стрелка: 0 * 6 = 0°
Часовая стрелка: (6 % 12) * 30 + 0 * 0.5 = 6 * 30 + 0 = 180°
Разница: |180 - 0| = 180°
✓ Результат: 180°

Пример 5: 9:45

Минутная стрелка: 45 * 6 = 270°
Часовая стрелка: (9 % 12) * 30 + 45 * 0.5 = 9 * 30 + 22.5 = 270 + 22.5 = 292.5°
Разница: |292.5 - 270| = 22.5°
✓ Результат: 22.5°

Визуализация

12:00                    12:15
    12                       12
  9   3                     9   3
    6                         6
Угол = 0°               Угол = 82.5°
(обе стрелки на 12)    (минутная на 3, часовая чуть дальше)

3:00                     6:00
    12                       12
  9   3 ←                   9   3
    6                       6 ←
Угол = 90°               Угол = 180°
(часовая на 3,          (стрелки напротив друг друга)
минутная на 12)

9:45
    12
  9 ←  3
    6
Угол = 22.5°
(обе стрелки близко к 9, минутная впереди)

Альтернативное решение (более компактное)

public class ClockAngleCompact {
    public static double getAngle(int hours, int minutes) {
        double minuteAngle = minutes * 6;
        double hourAngle = (hours % 12) * 30 + minutes * 0.5;
        
        double angle = Math.abs(hourAngle - minuteAngle);
        return Math.min(angle, 360 - angle);
    }
}

С использованием методов обработки ошибок

public class ClockAngleSafe {
    private static final int MINUTES_IN_HOUR = 60;
    private static final int HOURS_IN_CLOCK = 12;
    private static final double MINUTE_ANGLE_PER_MINUTE = 6.0;
    private static final double HOUR_ANGLE_PER_HOUR = 30.0;
    private static final double HOUR_ANGLE_PER_MINUTE = 0.5;
    private static final int FULL_ROTATION = 360;
    
    public static double getAngle(int hours, int minutes) {
        validateInput(hours, minutes);
        
        double minuteAngle = calculateMinuteAngle(minutes);
        double hourAngle = calculateHourAngle(hours, minutes);
        
        return calculateAngleBetween(minuteAngle, hourAngle);
    }
    
    private static void validateInput(int hours, int minutes) {
        if (hours < 0 || hours >= 24) {
            throw new IllegalArgumentException("Часы должны быть 0-23");
        }
        if (minutes < 0 || minutes >= MINUTES_IN_HOUR) {
            throw new IllegalArgumentException("Минуты должны быть 0-59");
        }
    }
    
    private static double calculateMinuteAngle(int minutes) {
        return minutes * MINUTE_ANGLE_PER_MINUTE;
    }
    
    private static double calculateHourAngle(int hours, int minutes) {
        hours = hours % HOURS_IN_CLOCK;
        return hours * HOUR_ANGLE_PER_HOUR + minutes * HOUR_ANGLE_PER_MINUTE;
    }
    
    private static double calculateAngleBetween(double angle1, double angle2) {
        double difference = Math.abs(angle1 - angle2);
        return Math.min(difference, FULL_ROTATION - difference);
    }
}

Тестирование

public class ClockAngleTest {
    public static void main(String[] args) {
        test(12, 0, 0.0);
        test(3, 0, 90.0);
        test(6, 0, 180.0);
        test(9, 0, 90.0);
        test(12, 15, 82.5);
        test(9, 45, 22.5);
        test(3, 15, 7.5);
        test(6, 30, 15.0);
        test(15, 0, 90.0);  // 3:00 PM → 90°
        test(21, 30, 75.0); // 9:30 PM → 75°
    }
    
    private static void test(int hours, int minutes, double expected) {
        double result = ClockAngle.getAngle(hours, minutes);
        boolean passed = Math.abs(result - expected) < 0.01;
        System.out.printf("%d:%02d → %.1f° (ожидали %.1f°) %s%n",
            hours, minutes, result, expected, passed ? "✓" : "✗");
    }
}

Сложность

Временная сложность: O(1) — только арифметические операции

Пространственная сложность: O(1) — используются только переменные

Ключевые моменты

  1. Часовая стрелка движется непрерывно — она не прыгает от часа к часу, а движется плавно
  2. Используйте модульhours % 12 для обработки 12-часового формата
  3. Возьмите минимум — из двух возможных углов (меньший и больший)
  4. Проверьте граничные случаи — 12:00 (полдень/полночь), 6:00 (противоположные стрелки)
Угол между стрелками часов | PrepBro