Как вы находите Leapyear в VBA? - PullRequest
10 голосов
/ 24 сентября 2008

Что такое хорошая реализация функции IsLeapYear в VBA?

Редактировать: Я запустил реализацию if-then и DateSerial с итерациями, завернутыми в таймер, и DateSerial был в среднем быстрее на 1-2 мс (5 прогонов по 300 итераций с 1 формула средней ячейки также работает).

Ответы [ 10 ]

21 голосов
/ 24 сентября 2008
Public Function isLeapYear(Yr As Integer) As Boolean  

    ' returns FALSE if not Leap Year, TRUE if Leap Year  

    isLeapYear = (Month(DateSerial(Yr, 2, 29)) = 2)  

End Function  

Первоначально я получил эту функцию с отличного сайта Чипа Пирсона в Excel.

Сайт Пирсона

14 голосов
/ 24 сентября 2008
public function isLeapYear (yr as integer) as boolean
    isLeapYear   = false
    if (mod(yr,400)) = 0 then isLeapYear  = true
    elseif (mod(yr,100)) = 0 then isLeapYear  = false
    elseif (mod(yr,4)) = 0 then isLeapYear  = true
end function

Википедия для более ... http://en.wikipedia.org/wiki/Leap_year

5 голосов
/ 25 сентября 2008

Если эффективность является соображением, а ожидаемый год является случайным, то, возможно, было бы лучше сначала сделать наиболее частый случай:

public function isLeapYear (yr as integer) as boolean
    if (mod(yr,4)) <> 0 then isLeapYear  = false
    elseif (mod(yr,400)) = 0 then isLeapYear  = true
    elseif (mod(yr,100)) = 0 then isLeapYear  = false
    else isLeapYear = true
end function
2 голосов
/ 08 августа 2011

В качестве варианта решения Chip Pearson вы также можете попробовать

Public Function isLeapYear(Yr As Integer) As Boolean  

  ' returns FALSE if not Leap Year, TRUE if Leap Year  

  isLeapYear = (DAY(DateSerial(Yr, 3, 0)) = 29)  

End Function
2 голосов
/ 25 сентября 2008

Я нашел этот забавный на CodeToad :

Public Function IsLeapYear(Year As Varient) As Boolean
  IsLeapYear = IsDate("29-Feb-" & Year)
End Function 

Хотя я вполне уверен, что использование IsDate в функции, вероятно, медленнее, чем пара if, elseifs.

1 голос
/ 05 июня 2018

Поздний ответ на вопрос о производительности.

TL / DR: версии Math примерно на 5x быстрее


Здесь я вижу две группы ответов

  1. Математическая интерпретация определения високосного года
  2. Использование функций даты / времени в Excel для обнаружения 29 февраля (они делятся на два лагеря: те, которые строят дату в виде строки, и те, которые не строят)

Я провел временные тесты для всех опубликованных ответов, обнаружил, что методы Math примерно на 5x быстрее , чем методы Date / Time.


Затем я провел некоторую оптимизацию методов и придумал (верите или нет Integer немного быстрее, чем Long в этом случае, не знаю почему.)

Function IsLeapYear1(Y As Integer) As Boolean
    If Y Mod 4 Then Exit Function
    If Y Mod 100 Then
    ElseIf Y Mod 400 Then Exit Function
    End If
    IsLeapYear1 = True
End Function

Для сравнения подошел (очень мало разницы по отношению к выложенной версии)

Public Function IsLeapYear2(yr As Integer) As Boolean
    IsLeapYear2 = Month(DateSerial(yr, 2, 29)) = 2
End Function

Версии даты / времени, которые строят дату в виде строки, были сброшены, поскольку они снова стали намного медленнее.

Тест должен был получить IsLeapYear в течение лет 100..9999, повторенный 1000 раз

Результаты

  • Математическая версия: 640ms
  • Дата / Время версия: 3360 мс

Тестовый код был

Sub Test()
    Dim n As Long, i As Integer, j As Long
    Dim d As Long
    Dim t1 As Single, t2 As Single
    Dim b As Boolean

    n = 1000

    Debug.Print "============================="
    t1 = Timer()
    For j = 1 To n
    For i = 100 To 9999
        b = IsYLeapYear1(i)
    Next i, j
    t2 = Timer()
    Debug.Print 1, (t2 - t1) * 1000

    t1 = Timer()
    For j = 1 To n
    For i = 100 To 9999
        b = IsLeapYear2(i)
    Next i, j
    t2 = Timer()
    Debug.Print 2, (t2 - t1) * 1000
End Sub
1 голос
/ 13 апреля 2017

Я вижу много великих понятий, которые указывают на дополнительное понимание и использование функций даты, которые потрясающе учиться у ... С точки зрения эффективности кода .. рассмотрим машинный код, необходимый для выполнения функции

вместо сложных функций даты использовать только довольно быстрые целочисленные функции Бейсик был построен на GOTO Я подозреваю, что что-то вроде ниже быстрее

  Function IsYLeapYear(Y%) As Boolean
     If Y Mod 4 <> 0 Then GoTo NoLY ' get rid of 75% of them
     If Y Mod 400 <> 0 And Y Mod 100 = 0 Then GoTo NoLY
     IsYLeapYear = True

NoLY:

 End Function
1 голос
/ 19 августа 2014
Public Function isLeapYear(Optional intYear As Variant) As Boolean

    If IsMissing(intYear) Then
        intYear = Year(Date)
    End If

    If intYear Mod 400 = 0 Then
        isLeapYear = True
    ElseIf intYear Mod 4 = 0 And intYear Mod 100 <> 0 Then
        isLeapYear = True
    End If

End Function
1 голос
/ 28 сентября 2013
Public Function ISLeapYear(Y As Integer) AS Boolean
 ' Uses a 2 or 4 digit year
'To determine whether a year is a leap year, follow these steps:
'1    If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
'2    If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
'3    If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
'4    The year is a leap year (it has 366 days).
'5    The year is not a leap year (it has 365 days).

If Y Mod 4 = 0 Then ' This is Step 1 either goto step 2 else step 5
    If Y Mod 100 = 0 Then ' This is Step 2 either goto step 3 else step 4
        If Y Mod 400 = 0 Then ' This is Step 3 either goto step 4 else step 5
            ISLeapYear = True ' This is Step 4 from step 3
                Exit Function
        Else: ISLeapYear = False ' This is Step 5 from step 3
                Exit Function
        End If
    Else: ISLeapYear = True ' This is Step 4 from Step 2
            Exit Function
    End If
Else: ISLeapYear = False ' This is Step 5 from Step 1
End If


End Function
0 голосов
/ 19 ноября 2015

Вот еще один простой вариант.

Leap_Day_Check = Day(DateValue("01/03/" & Required_Year) - 1)

Если Leap_Day_Check = 28, то это не високосный год, если 29, то это *. 1004 *

VBA знает, какая дата наступает до 1 марта в году, поэтому для нас она будет 28 или 29 февраля.

...