vb.net 如果 Mod = 0,是做多个 OrElse 更好还是单次检查
vb.net Is it better to do multiple OrElse's, or a single check if Mod = 0
有两种简单的方法可以检查一个月是否是季度的第一天。
第一种方式:
If month = 3 OrElse month = 6 OrElse month = 9 OrElse month = 12 Then
'do stuff
End If
第二种方式:
If month Mod 3 = 0 Then
'do stuff
End If
对我来说,它们都同样可读。尽管它们在功能上有所不同,但只要知道月份在 1 到 12 之间(包括 1 和 12),它们就是相同的逻辑。应该使用哪种方式?
在最坏的情况下,如果month = 12
,则执行四次比较。做一个模数和一个比较是否更快(不是显着的性能差异)?
正如DaveDoknjas在上面的评论中所说,使用更清楚逻辑的方法。
如果你的逻辑决定你必须做某事,因为月份是一年中的第 3、6、9 或 12 个月,请使用:
If month = 3 OrElse month = 6 OrElse month = 9 OrElse month = 12 Then
'do stuff
End If
但是,另一方面,如果您需要做某事因为月份数可以被 3 整除,请使用:
If month Mod 3 = 0 Then
'do stuff
End If
性能上的差异非常小,不会引起注意。最后,当您需要它们时,它们都会评估为 True
,因此这实际上取决于偏好以及您认为合乎逻辑和可读性的内容。
您表达了使用可读性好和性能良好的测试的愿望。
您在设计性能测试时必须小心:如果您只有评论部分 "executed" 那么在发布模式下它可能会被完全优化掉,即测试将不在 运行 的最终代码中,您不会为该测试计时。
你必须把一些无法优化的操作去掉,并且不要淹没时间。我使用了一个值的赋值,该值在使用时可能在处理器寄存器中,或者至少在处理器缓存中。
因此,您的测试可能看起来像
Module Module1
Sub Main()
' set up plenty of test data
Dim rand As New Random
Dim nTestMonths = 10000
Dim testMonths(nTestMonths - 1) As Integer
For i = 0 To nTestMonths - 1
testMonths(i) = rand.Next(1, 13)
Next
' time a lot of tests
Dim sw As New Stopwatch
Dim nTests = 100000
Dim dummyVar As Integer
' run the tests in one order...
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) = 3 OrElse testMonths(j) = 6 OrElse testMonths(j) = 9 OrElse testMonths(j) = 12 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) Mod 3 = 0 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
' this test takes about nine times longer than the others
' so it is commented out.
'Dim quarterStarts As New List(Of Integer) From {3, 6, 9, 12}
'sw.Restart()
'For i = 1 To nTests
' For j = 0 To nTestMonths - 1
' If quarterStarts.Contains(testMonths(j)) Then
' dummyVar = testMonths(j)
' End If
' Next
'Next
'sw.Stop()
'Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
Select Case testMonths(j)
Case 3, 6, 9, 12
dummyVar = testMonths(j)
End Select
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
' now run the tests in a different order...
Console.WriteLine("Tests in reverse order...")
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
Select Case testMonths(j)
Case 3, 6, 9, 12
dummyVar = testMonths(j)
End Select
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
'sw.Restart()
'For i = 1 To nTests
' For j = 0 To nTestMonths - 1
' If quarterStarts.Contains(testMonths(j)) Then
' dummyVar = testMonths(j)
' End If
' Next
'Next
'sw.Stop()
'Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) Mod 3 = 0 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) = 3 OrElse testMonths(j) = 6 OrElse testMonths(j) = 9 OrElse testMonths(j) = 12 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
Console.ReadLine()
End Sub
End Module
结果类似于
10.047
18.001
6.722
Tests in reverse order...
6.463
17.604
10.254
所以你可以看到 The_Black_Smurf 的建议使用 Select Case
语句具有很好的可读性 和 恰好是最快的。
有两种简单的方法可以检查一个月是否是季度的第一天。
第一种方式:
If month = 3 OrElse month = 6 OrElse month = 9 OrElse month = 12 Then
'do stuff
End If
第二种方式:
If month Mod 3 = 0 Then
'do stuff
End If
对我来说,它们都同样可读。尽管它们在功能上有所不同,但只要知道月份在 1 到 12 之间(包括 1 和 12),它们就是相同的逻辑。应该使用哪种方式?
在最坏的情况下,如果month = 12
,则执行四次比较。做一个模数和一个比较是否更快(不是显着的性能差异)?
正如DaveDoknjas在上面的评论中所说,使用更清楚逻辑的方法。
如果你的逻辑决定你必须做某事,因为月份是一年中的第 3、6、9 或 12 个月,请使用:
If month = 3 OrElse month = 6 OrElse month = 9 OrElse month = 12 Then
'do stuff
End If
但是,另一方面,如果您需要做某事因为月份数可以被 3 整除,请使用:
If month Mod 3 = 0 Then
'do stuff
End If
性能上的差异非常小,不会引起注意。最后,当您需要它们时,它们都会评估为 True
,因此这实际上取决于偏好以及您认为合乎逻辑和可读性的内容。
您表达了使用可读性好和性能良好的测试的愿望。
您在设计性能测试时必须小心:如果您只有评论部分 "executed" 那么在发布模式下它可能会被完全优化掉,即测试将不在 运行 的最终代码中,您不会为该测试计时。
你必须把一些无法优化的操作去掉,并且不要淹没时间。我使用了一个值的赋值,该值在使用时可能在处理器寄存器中,或者至少在处理器缓存中。
因此,您的测试可能看起来像
Module Module1
Sub Main()
' set up plenty of test data
Dim rand As New Random
Dim nTestMonths = 10000
Dim testMonths(nTestMonths - 1) As Integer
For i = 0 To nTestMonths - 1
testMonths(i) = rand.Next(1, 13)
Next
' time a lot of tests
Dim sw As New Stopwatch
Dim nTests = 100000
Dim dummyVar As Integer
' run the tests in one order...
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) = 3 OrElse testMonths(j) = 6 OrElse testMonths(j) = 9 OrElse testMonths(j) = 12 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) Mod 3 = 0 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
' this test takes about nine times longer than the others
' so it is commented out.
'Dim quarterStarts As New List(Of Integer) From {3, 6, 9, 12}
'sw.Restart()
'For i = 1 To nTests
' For j = 0 To nTestMonths - 1
' If quarterStarts.Contains(testMonths(j)) Then
' dummyVar = testMonths(j)
' End If
' Next
'Next
'sw.Stop()
'Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
Select Case testMonths(j)
Case 3, 6, 9, 12
dummyVar = testMonths(j)
End Select
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
' now run the tests in a different order...
Console.WriteLine("Tests in reverse order...")
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
Select Case testMonths(j)
Case 3, 6, 9, 12
dummyVar = testMonths(j)
End Select
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
'sw.Restart()
'For i = 1 To nTests
' For j = 0 To nTestMonths - 1
' If quarterStarts.Contains(testMonths(j)) Then
' dummyVar = testMonths(j)
' End If
' Next
'Next
'sw.Stop()
'Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) Mod 3 = 0 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
sw.Restart()
For i = 1 To nTests
For j = 0 To nTestMonths - 1
If testMonths(j) = 3 OrElse testMonths(j) = 6 OrElse testMonths(j) = 9 OrElse testMonths(j) = 12 Then
dummyVar = testMonths(j)
End If
Next
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds / 1000)
Console.ReadLine()
End Sub
End Module
结果类似于
10.047
18.001
6.722
Tests in reverse order...
6.463
17.604
10.254
所以你可以看到 The_Black_Smurf 的建议使用 Select Case
语句具有很好的可读性 和 恰好是最快的。