문제

VBA에서 ISLEAPYEAR 기능의 좋은 구현은 무엇입니까?

편집하다: 나는 타이머에 반복이 감겨있는 IF-THEN과 데이트 레알 구현을 실행했으며, 날짜는 평균적으로 1-2ms (300 회 반복의 5 개 실행, 1 개의 평균 셀 워크 시트 공식도 작동 함)를 평균적으로 더 빠르게 수행했습니다.

도움이 되었습니까?

해결책

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  

나는 원래 Chip Pearson의 Great Excel 사이트 에서이 기능을 얻었습니다.

피어슨의 사이트

다른 팁

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

더 많은 Wikipedia ...http://en.wikipedia.org/wiki/leap_year

효율성이 고려 사항이고 예상 연도가 무작위 인 경우 가장 먼저 가장 빈번한 사례를 수행하는 것이 약간 더 나을 수 있습니다.

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

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

나는이 재미있는 것을 발견했다 코드로드 :

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

하지만 기능에서 ISDATE를 사용하는 것이 아마도 몇 가지 if, elseifs보다 느리게 느려질 것이라고 확신합니다.

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
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

코드 효율성 측면에서 배울 수있는 데이트 기능의 추가 이해와 사용법을 나타내는 많은 훌륭한 개념을 봅니다. 기능이 실행하는 데 필요한 기계 코드를 고려하십시오.

복잡한 날짜 기능보다는 상당히 빠른 정수 기능 만 사용하는 대신 기본적으로 기본적으로 구축되었습니다.

  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

성능 질문을 해결하기위한 늦은 답변.

tl/dr : the 수학 버전이 있습니다 더 빨리 5 배 더


여기서 두 그룹의 답변이 보입니다

  1. 도약 연도 정의의 수학적 해석
  2. Excel 날짜/시간 기능을 활용하여 2 월 29 일을 감지합니다 (이것은 두 개의 캠프에 속합니다 : 날짜를 끈으로 구축하는 것과 그렇지 않은 것들)

나는 모든 게시 된 답변에서 시간 테스트를 실행했다. 수학 방법이 있습니다 더 빨리 5 배 더 날짜/시간 방법보다.


그런 다음 방법을 최적화하고 생각해 냈습니다 (믿거 나 말거나 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
  • 날짜/시간 버전 : 3360ms

테스트 코드였습니다

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

또 다른 간단한 옵션이 있습니다.

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

leap_day_check = 28 인 경우 29 세가되는 경우 도약이 아닙니다.

VBA는 3 월 1 일 이전의 날짜가 1 년에 무엇인지 알고 있으며 2 월 28 일 또는 29 일로 설정 될 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top