كيف تجد Leapyear في VBA؟
-
02-07-2019 - |
سؤال
ما هو التنفيذ الجيد لوظيفة IsLeapYear في VBA؟
يحرر: لقد قمت بتشغيل تنفيذ if-then وDateSerial مع تكرارات ملفوفة في جهاز توقيت، وكان DateSerial أسرع في المتوسط بمقدار 1-2 مللي ثانية (5 عمليات تشغيل من 300 تكرار، مع صيغة ورقة عمل خلية واحدة متوسطة تعمل أيضًا).
المحلول
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 الرائع الخاص بـ Chip Pearson.
نصائح أخرى
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.
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
إجابة متأخرة لمعالجة سؤال الأداء.
ليرة تركية/دكتور:ال الرياضيات الإصدارات حول أسرع بـ 5 مرات
أرى مجموعتين من الإجابات هنا
- التفسير الرياضي لتعريف السنة الكبيسة
- استخدم وظائف التاريخ/الوقت في Excel للكشف عن 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 مرة
نتائج
- نسخة الرياضيات:640 مللي ثانية
- إصدار التاريخ/الوقت: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
إليك خيارًا بسيطًا آخر.
Leap_Day_Check = Day(DateValue("01/03/" & Required_Year) - 1)
إذا كانت Leap_Day_Check = 28 فهي ليست سنة كبيسة، وإذا كانت 29 فهي كذلك.
يعرف VBA التاريخ الذي يسبق الأول من مارس خلال عام ولذلك سيحدده ليكون إما 28 أو 29 فبراير بالنسبة لنا.