How do you Leap Year in VBA finden?
-
02-07-2019 - |
Frage
Was ist eine gute Umsetzung einer IsLeapYear Funktion in VBA?
Bearbeiten: Ich lief das if-then und die DatSeriell Implementierung mit umwickelten Iterationen in einem Timer und die DatSeriell war schneller im Durchschnitt um 1-2 ms (5 Läufe von 300 Iterationen, mit mittlere Zell 1 Arbeitsblatt Formel auch arbeiten).
Lösung
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
Ich habe ursprünglich diese Funktion von Chip Pearson große Excel-Website.
Andere Tipps
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 für mehr ... http://en.wikipedia.org/wiki/Leap_year
Wenn Effizienz ist eine Überlegung und das erwartete Jahr ist zufällig, dann könnte es etwas besser, die häufigste Fall zuerst zu tun:
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
Als Variante des Chip Pearson Lösung, könnten Sie auch versuchen,
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
Ich fand diesen lustig man auf CodeToad :
Public Function IsLeapYear(Year As Varient) As Boolean
IsLeapYear = IsDate("29-Feb-" & Year)
End Function
Obwohl ich bin mir ziemlich sicher, dass die Verwendung von IsDate in einer Funktion ist wahrscheinlich langsamer als ein paar, wenn 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
Ich sehe viele große Konzepte, die zusätzliche Verständnis zeigen und die Verwendung von Datumsfunktionen, die grandios sind zu lernen ... In Bezug auf die Code-Effizienz .. Sehen Sie den Maschinencode für eine Funktion benötigt, um auszuführen
anstatt komplexe Datumsfunktionen verwenden nur ziemlich schnelle Integer-Funktionen BASIC wurde auf GOTO gebaut Ich vermute, dass so etwas wie unten schneller
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
Späte Antwort, die Leistung Frage zu beantworten.
TL / DR: die Math Versionen sind über 5x schneller
Ich sehe zwei Gruppen von Antworten hier
- Mathematische Interpretation der Schaltjahr-Definition
- Nutzen Sie die Excel-Datum / Zeit-Funktionen 29. Februar zu erfassen (diese fallen in zwei Lager: diejenigen, die ein Datum als String bauen und solche, die dies nicht tun)
Ich lief Zeittests auf allen geschrieben Antworten, eine entdeckte die Math Methoden sind über 5x schneller als die Datum / Zeit-Methoden.
Ich habe dann einige Optimierung der Methoden und kam mit (es glauben oder nicht Integer
ist geringfügig schneller als Long
in diesem Fall weiß nicht, warum.) Bis
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
Zum Vergleich kam ich (sehr wenig Unterschied zu der entsandten Version)
Public Function IsLeapYear2(yr As Integer) As Boolean
IsLeapYear2 = Month(DateSerial(yr, 2, 29)) = 2
End Function
Das Datum / Zeit-Versionen, die ein Datum als String diskon bauen wurden sie wieder viel langsamer sind.
Der Test IsLeapYear
jahrelang 100..9999, wiederholt 1000 mal
Ergebnisse
- Math Version: 640ms
- Datum / Uhrzeit Version: 3360ms
Der Testcode war
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
Hier ist eine weitere einfache Möglichkeit.
Leap_Day_Check = Day(DateValue("01/03/" & Required_Year) - 1)
Wenn Leap_Day_Check 28 = dann ist es kein Schaltjahr, wenn es 29 ist es ist.
VBA weiß, was das Datum vor dem 1. März in einem Jahr ist und so setzt sie entweder 28 oder 29. Februar für uns sein.