Modify

#2922 closed Feature Request (Completed)

Better reliability for _VersionCompare()

Reported by: Synix <cross.fire@…> Owned by: Jpm
Milestone: 3.3.13.20 Component: Standard UDFs
Version: Severity: None
Keywords: Cc:

Description

In ticket #1881 someone stated that version comparing returns incorrect values in some cases. I also encountered these issues some times, so I wanted to suggest you to change the code to my following proposal:

Func _VersionCompare($sVersion1, $sVersion2)
	If $sVersion1 = $sVersion2 Then Return 0
	Local $aVersion1 = StringSplit($sVersion1, ".,"), _
			$aVersion2 = StringSplit($sVersion2, ".,")
	Local $iPartDifference = ($aVersion1[0] - $aVersion2[0])
	If $iPartDifference < 0 Then
		;$sVersion1 consists of less parts, fill the missing parts with zeros
		ReDim $aVersion1[UBound($aVersion2)]
		$aVersion1[0] = UBound($aVersion1) - 1
		For $i = (UBound($aVersion1) - Abs($iPartDifference)) To $aVersion1[0]
			$aVersion1[$i] = "0"
		Next
	ElseIf $iPartDifference > 0 Then
		;$sVersion2 consists of less parts, fill the missing parts with zeros
		ReDim $aVersion2[UBound($aVersion1)]
		$aVersion2[0] = UBound($aVersion2) - 1
		For $i = (UBound($aVersion2) - Abs($iPartDifference)) To $aVersion2[0]
			$aVersion2[$i] = "0"
		Next
	EndIf
	For $i = 1 To $aVersion1[0]
		; Compare this segment as numbers
		If StringIsDigit($aVersion1[$i]) And StringIsDigit($aVersion2[$i]) Then
			If Number($aVersion1[$i]) > Number($aVersion2[$i]) Then
				Return SetExtended(2, 1) ; @extended set to 2 for number comparison.
			ElseIf Number($aVersion1[$i]) < Number($aVersion2[$i]) Then
				Return SetExtended(2, -1) ; @extended set to 2 for number comparison.
			EndIf
		Else ; Compare the segment as strings
			If $aVersion1[$i] > $aVersion2[$i] Then
				Return SetExtended(1, 1) ; @extended set to 1 for string comparison.
			ElseIf $aVersion1[$i] < $aVersion2[$i] Then
				Return SetExtended(1, -1) ; @extended set to 1 for string comparison.
			EndIf
		EndIf
	Next
	; This point should never be reached
	Return SetError(2, 0, 0)
EndFunc   ;==>_VersionCompare

This basically equals the "part length" for both versions before comparing, which leads to precise numerical comparisons (if both input versions are numerical). This eliminates all errors on numerical version compares with unequal part lentghs like _VersionCompare("1.2.1", "1.10").
When comparing versions with unequal part lengths, that have non-numerical parts at the end, it will eliminate incorrect return values in cases like _VersionCompare("1.11.1b", "1.2") for example.
Some thing to note though is, that this can not "fix" string comparisons like "1.1b" to "1.11c" for example, due to the nature of the lexicographical comparison.

Attachments (0)

Change History (4)

comment:1 by TicketCleanup, on Oct 13, 2014 at 2:00:01 AM

Version: 3.3.12.0

Automatic ticket cleanup.

comment:2 by Jpm, on Oct 14, 2014 at 9:04:20 AM

Do you have objection if i change?

		; Compare this segment as numbers
		If StringIsDigit(StringLeft($aVersion1[$i], 1)) And StringIsDigit(StringLeft($aVersion2[$i], 1)) Then

It can allow "1.1b" to "1.11c"

comment:3 by Jpm, on Oct 14, 2014 at 1:18:22 PM

Milestone: 3.3.13.20
Owner: set to Jpm
Resolution: Completed
Status: newclosed

Added by revision [11131] in version: 3.3.13.20

comment:4 by Synix <cross.fire@…>, on Oct 17, 2014 at 7:43:46 PM

Nice idea :) thanks.
You could even go completely nuts and separate the numbers from letters using RegEx and compare each part after that, but that would be quite an overkill code-wise and most cases of version numbers will be covered with the coming update anyways.

Modify Ticket

Action
as closed The owner will remain Jpm.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.