prosource

VBA에서 Leapyear를 어떻게 찾습니까?

probook 2023. 10. 30. 21:04
반응형

VBA에서 Leapyear를 어떻게 찾습니까?

VBA에서 IsLapYear 기능을 잘 구현한 것은 무엇입니까?

편집: if-then 및 DateSerial 구현을 타이머로 감싼 상태에서 실행한 결과 DateSerial이 평균적으로 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  

저는 원래 칩 피어슨의 훌륭한 엑셀 사이트에서 이 기능을 얻었습니다.

피어슨 사이트

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

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

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

CodeToad에서 이 재미있는 것을 발견했습니다.

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

함수에서 IsDate를 사용하는 것은 아마도 여러 if, elseifs보다 느릴 것이라고 확신합니다.

성능 문제를 해결하기 위한 늦은 답변.

TL/DR: 수학 버전이 약 5배빠릅니다.


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

  1. 윤년 정의의 수학적 해석
  2. Excel Date/Time 기능을 활용하여 Feb 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

날짜를 문자열로 작성하는 Date/Time 버전은 다시 훨씬 느려지기 때문에 할인됩니다.

시험은 다음과 같이 하기로 되어 있었습니다.IsLeapYear100년동안..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
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

데이트 기능에 대한 추가적인 이해와 사용법을 나타내는 많은 훌륭한 개념들을 볼 수 있습니다. 이 개념들은...에서 배울 수 있는 멋진 것들입니다.코드 효율성 측면에서..함수를 실행하는 데 필요한 기계 코드를 고려합니다.

복잡한 날짜 함수보다는 꽤 빠른 정수 함수만 사용합니다. 베이직은 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

노리:

 End Function

여기 또 하나의 간단한 옵션이 있습니다.

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

Leap_Day_Check = 28이면 윤년이 아니고 29이면 윤년입니다.

VBA는 1년 후 3월 1일 이전 날짜를 알고 있으며, 2월 28일 또는 29일로 설정할 예정입니다.

언급URL : https://stackoverflow.com/questions/128104/how-do-you-find-leapyear-in-vba

반응형