VB6Parse / Library / Math / sgn

VB6 Library Reference

Sgn Function

Returns an Integer indicating the sign of a number.

Syntax

Sgn(number)

Parameters

Return Value

Returns an Integer indicating the sign of the number: - Returns -1 if number is negative (less than zero) - Returns 0 if number is zero - Returns 1 if number is positive (greater than zero)

Remarks

The Sgn function is used to determine the sign (positive, negative, or zero) of a numeric expression. It is particularly useful for: - Determining the direction of change in values - Implementing sign-dependent logic without complex conditionals - Comparing signs of two numbers - Normalizing values to -1, 0, or 1 - Mathematical algorithms requiring sign information

The sign of number determines the return value: - If number > 0, Sgn returns 1 - If number = 0, Sgn returns 0 - If number < 0, Sgn returns -1

If number is Null, Sgn returns Null.

The Sgn function is often used in combination with Abs to separate magnitude from direction: - Abs(number) gives the magnitude (absolute value) - Sgn(number) gives the direction (sign) - number = Abs(number) * Sgn(number) (reconstruction)

Typical Uses

  1. Direction Detection: Determine if a value is increasing or decreasing
  2. Sign Comparison: Compare signs of two numbers
  3. Conditional Logic: Simplify sign-based branching
  4. Mathematical Operations: Algorithms requiring sign information
  5. Data Validation: Check if values are positive, negative, or zero
  6. Trend Analysis: Determine direction of change in time series
  7. Game Logic: Movement direction, score changes
  8. Financial Calculations: Profit/loss direction, balance changes

Basic Examples

' Example 1: Basic sign detection
Dim result As Integer
result = Sgn(10)      ' Returns 1 (positive)
result = Sgn(-5.5)    ' Returns -1 (negative)
result = Sgn(0)       ' Returns 0 (zero)
' Example 2: Determine direction of change
Dim oldValue As Double
Dim newValue As Double
Dim direction As Integer

oldValue = 100
newValue = 120
direction = Sgn(newValue - oldValue)  ' Returns 1 (increasing)

If direction = 1 Then
MsgBox "Value increased"
ElseIf direction = -1 Then
MsgBox "Value decreased"
Else
MsgBox "No change"
End If
' Example 3: Compare signs of two numbers
Dim a As Double
Dim b As Double

a = -15
b = -20

If Sgn(a) = Sgn(b) Then
MsgBox "Same sign"
Else
MsgBox "Different signs"
End If
' Example 4: Normalize to unit sign
Dim value As Double
Dim unitSign As Integer

value = 42.7
unitSign = Sgn(value)  ' Returns 1
' Now unitSign can be used as a multiplier: 1, 0, or -1

Common Patterns

Pattern 1: GetChangeDirection

Determine if value increased, decreased, or stayed same

Function GetChangeDirection(oldVal As Double, newVal As Double) As String
Dim direction As Integer
direction = Sgn(newVal - oldVal)

Select Case direction
Case 1
GetChangeDirection = "Increased"
Case -1
GetChangeDirection = "Decreased"
Case 0
GetChangeDirection = "No Change"
End Select
End Function

Pattern 2: SameSign

Check if two numbers have the same sign

Function SameSign(a As Double, b As Double) As Boolean
' Both zero, or both have same non-zero sign
If a = 0 And b = 0 Then
SameSign = True
Else
SameSign = (Sgn(a) = Sgn(b))
End If
End Function

Pattern 3: OppositeSign

Check if two numbers have opposite signs

Function OppositeSign(a As Double, b As Double) As Boolean
OppositeSign = (Sgn(a) = -Sgn(b)) And (a <> 0) And (b <> 0)
End Function

Pattern 4: SignMultiplier

Get sign as multiplier for calculations

Function SignMultiplier(value As Double) As Integer
SignMultiplier = Sgn(value)
' Returns: -1, 0, or 1 which can be used in calculations
End Function

Pattern 5: ClampToSign

Ensure value has specific sign

Function ClampToSign(value As Double, requiredSign As Integer) As Double
If Sgn(value) <> requiredSign Then
ClampToSign = Abs(value) * requiredSign
Else
ClampToSign = value
End If
End Function

Pattern 6: SignString

Convert sign to string representation

Function SignString(value As Double) As String
Select Case Sgn(value)
Case 1
SignString = "+"
Case -1
SignString = "-"
Case 0
SignString = "0"
End Select
End Function

Pattern 7: CompareBySign

Three-way comparison using sign

Function CompareBySign(a As Double, b As Double) As Integer
' Returns: -1 if a < b, 0 if a = b, 1 if a > b
CompareBySign = Sgn(a - b)
End Function

Pattern 8: CountBySign

Count positive, negative, and zero values

Sub CountBySign(arr() As Double, ByRef positive As Long, _
ByRef negative As Long, ByRef zero As Long)
Dim i As Long
positive = 0
negative = 0
zero = 0

For i = LBound(arr) To UBound(arr)
Select Case Sgn(arr(i))
Case 1
positive = positive + 1
Case -1
negative = negative + 1
Case 0
zero = zero + 1
End Select
Next i
End Sub

Pattern 9: TrendDirection

Determine overall trend in series

Function TrendDirection(values() As Double) As String
Dim i As Long
Dim changes As Long
Dim positiveChanges As Long
Dim negativeChanges As Long

For i = LBound(values) + 1 To UBound(values)
Dim change As Integer
change = Sgn(values(i) - values(i - 1))

If change = 1 Then positiveChanges = positiveChanges + 1
If change = -1 Then negativeChanges = negativeChanges + 1
Next i

If positiveChanges > negativeChanges Then
TrendDirection = "Upward"
ElseIf negativeChanges > positiveChanges Then
TrendDirection = "Downward"
Else
TrendDirection = "Stable"
End If
End Function

Pattern 10: ApplySignTo

Apply sign of one number to another

Function ApplySignTo(magnitude As Double, signSource As Double) As Double
' Take absolute value of magnitude and apply sign from signSource
ApplySignTo = Abs(magnitude) * Sgn(signSource)
End Function

Advanced Usage

Example 1: ChangeAnalyzer Class

Analyze changes in data series with trend detection

' Class: ChangeAnalyzer
Private m_values() As Double
Private m_count As Long

Public Sub Initialize(initialCapacity As Long)
ReDim m_values(1 To initialCapacity)
m_count = 0
End Sub

Public Sub AddValue(value As Double)
m_count = m_count + 1

If m_count > UBound(m_values) Then
ReDim Preserve m_values(1 To m_count * 2)
End If

m_values(m_count) = value
End Sub

Public Function GetChangeDirection(index As Long) As Integer
' Returns direction of change at index
If index < 2 Or index > m_count Then
GetChangeDirection = 0
Else
GetChangeDirection = Sgn(m_values(index) - m_values(index - 1))
End If
End Function

Public Function GetOverallTrend() As String
Dim i As Long
Dim upCount As Long
Dim downCount As Long

For i = 2 To m_count
Select Case Sgn(m_values(i) - m_values(i - 1))
Case 1
upCount = upCount + 1
Case -1
downCount = downCount + 1
End Select
Next i

If upCount > downCount Then
GetOverallTrend = "Upward Trend"
ElseIf downCount > upCount Then
GetOverallTrend = "Downward Trend"
Else
GetOverallTrend = "No Clear Trend"
End If
End Function

Public Function GetConsecutiveChanges() As Long
' Find longest sequence of consecutive changes in same direction
Dim i As Long
Dim currentDirection As Integer
Dim currentCount As Long
Dim maxCount As Long

If m_count < 2 Then
GetConsecutiveChanges = 0
Exit Function
End If

currentDirection = Sgn(m_values(2) - m_values(1))
currentCount = 1
maxCount = 1

For i = 3 To m_count
Dim direction As Integer
direction = Sgn(m_values(i) - m_values(i - 1))

If direction = currentDirection And direction <> 0 Then
currentCount = currentCount + 1
If currentCount > maxCount Then maxCount = currentCount
Else
currentDirection = direction
currentCount = 1
End If
Next i

GetConsecutiveChanges = maxCount
End Function

Public Function GetTrendStrength() As Double
' Returns value between -1 and 1 indicating trend strength
' 1 = strong upward, -1 = strong downward, 0 = no trend
Dim i As Long
Dim sumSign As Long
Dim changes As Long

For i = 2 To m_count
Dim sign As Integer
sign = Sgn(m_values(i) - m_values(i - 1))
If sign <> 0 Then
sumSign = sumSign + sign
changes = changes + 1
End If
Next i

If changes > 0 Then
GetTrendStrength = CDbl(sumSign) / CDbl(changes)
Else
GetTrendStrength = 0
End If
End Function

Example 2: SignComparator Module

Compare and analyze signs in numeric data

' Module: SignComparator

Public Function AllSameSign(values() As Double) As Boolean
' Check if all values have the same sign
Dim i As Long
Dim firstSign As Integer

If UBound(values) < LBound(values) Then
AllSameSign = True
Exit Function
End If

' Get first non-zero sign
firstSign = 0
For i = LBound(values) To UBound(values)
firstSign = Sgn(values(i))
If firstSign <> 0 Then Exit For
Next i

' Check all others
For i = LBound(values) To UBound(values)
If Sgn(values(i)) <> 0 And Sgn(values(i)) <> firstSign Then
AllSameSign = False
Exit Function
End If
Next i

AllSameSign = True
End Function

Public Function GetSignCounts(values() As Double) As String
Dim i As Long
Dim posCount As Long
Dim negCount As Long
Dim zeroCount As Long

For i = LBound(values) To UBound(values)
Select Case Sgn(values(i))
Case 1
posCount = posCount + 1
Case -1
negCount = negCount + 1
Case 0
zeroCount = zeroCount + 1
End Select
Next i

GetSignCounts = "Positive: " & posCount & _
", Negative: " & negCount & _
", Zero: " & zeroCount
End Function

Public Function AlternatingSign(values() As Double) As Boolean
' Check if signs alternate (ignoring zeros)
Dim i As Long
Dim lastSign As Integer

For i = LBound(values) To UBound(values)
Dim currentSign As Integer
currentSign = Sgn(values(i))

If currentSign <> 0 Then
If lastSign <> 0 And currentSign = lastSign Then
AlternatingSign = False
Exit Function
End If
lastSign = currentSign
End If
Next i

AlternatingSign = True
End Function

Public Function SignTransitions(values() As Double) As Long
' Count how many times the sign changes
Dim i As Long
Dim transitions As Long
Dim lastSign As Integer

For i = LBound(values) To UBound(values)
Dim currentSign As Integer
currentSign = Sgn(values(i))

If currentSign <> 0 Then
If lastSign <> 0 And currentSign <> lastSign Then
transitions = transitions + 1
End If
lastSign = currentSign
End If
Next i

SignTransitions = transitions
End Function

Example 3: DirectionIndicator Class

Track and display directional changes with symbols

' Class: DirectionIndicator
Private m_lastValue As Double
Private m_initialized As Boolean

Public Sub SetInitialValue(value As Double)
m_lastValue = value
m_initialized = True
End Sub

Public Function UpdateAndGetSymbol(newValue As Double) As String
If Not m_initialized Then
m_lastValue = newValue
m_initialized = True
UpdateAndGetSymbol = "―"  ' Neutral symbol
Exit Function
End If

Dim direction As Integer
direction = Sgn(newValue - m_lastValue)

Select Case direction
Case 1
UpdateAndGetSymbol = "▲"  ' Up arrow
Case -1
UpdateAndGetSymbol = "▼"  ' Down arrow
Case 0
UpdateAndGetSymbol = "―"  ' Neutral
End Select

m_lastValue = newValue
End Function

Public Function GetDirection() As String
' Not implemented - would require storing current value
GetDirection = "N/A"
End Function

Public Function GetChangeText(newValue As Double) As String
If Not m_initialized Then
GetChangeText = "Initial Value"
Else
Dim change As Double
Dim direction As Integer

change = newValue - m_lastValue
direction = Sgn(change)

Select Case direction
Case 1
GetChangeText = "Increased by " & Abs(change)
Case -1
GetChangeText = "Decreased by " & Abs(change)
Case 0
GetChangeText = "No Change"
End Select
End If
End Function

Public Sub Reset()
m_initialized = False
m_lastValue = 0
End Sub

Example 4: MathSignHelper Module

Mathematical operations using sign function

' Module: MathSignHelper

Public Function CopySign(magnitude As Double, signSource As Double) As Double
' Copy the sign from signSource to magnitude
' Similar to copysign() in C math library
CopySign = Abs(magnitude) * Sgn(signSource)
End Function

Public Function RoundAwayFromZero(value As Double) As Long
' Round away from zero (ceiling for positive, floor for negative)
Dim sign As Integer
sign = Sgn(value)

If sign >= 0 Then
RoundAwayFromZero = -Int(-value)  ' Ceiling
Else
RoundAwayFromZero = Int(value)    ' Floor
End If
End Function

Public Function RoundTowardZero(value As Double) As Long
' Round toward zero (floor for positive, ceiling for negative)
RoundTowardZero = Fix(value)
End Function

Public Function StepInDirection(value As Double, stepSize As Double, _
direction As Integer) As Double
' Step in the direction indicated by sign (-1, 0, or 1)
StepInDirection = value + (Abs(stepSize) * direction)
End Function

Public Function Clamp(value As Double, minVal As Double, maxVal As Double) As Double
' Clamp value between min and max
If value < minVal Then
Clamp = minVal
ElseIf value > maxVal Then
Clamp = maxVal
Else
Clamp = value
End If
End Function

Public Function SignedMin(a As Double, b As Double) As Double
' Return the value with smaller absolute value, preserving sign
If Abs(a) < Abs(b) Then
SignedMin = a
Else
SignedMin = b
End If
End Function

Public Function SignedMax(a As Double, b As Double) As Double
' Return the value with larger absolute value, preserving sign
If Abs(a) > Abs(b) Then
SignedMax = a
Else
SignedMax = b
End If
End Function

Public Function CompareNumbers(a As Double, b As Double) As Integer
' Three-way comparison: -1 if a<b, 0 if a=b, 1 if a>b
CompareNumbers = Sgn(a - b)
End Function

Error Handling

The Sgn function can generate the following errors:

Always use error handling when working with user input or uncertain data:

On Error Resume Next
result = Sgn(userValue)
If Err.Number <> 0 Then
MsgBox "Invalid numeric value"
End If

Performance Considerations

Best Practices

  1. Use for Comparisons: Prefer Sgn(a - b) over complex If statements for three-way comparison
  2. Handle Zero Case: Remember that zero has its own return value (0)
  3. Type Safety: Ensure argument is numeric to avoid Type Mismatch error
  4. Null Handling: Check for Null if input might be Null
  5. Sign vs. Value: Don't confuse sign with actual value
  6. Combine with Abs: Use together to separate magnitude and direction
  7. Clear Intent: Use Sgn to make sign-dependent logic more readable
  8. Avoid Redundancy: Don't use Sgn(Abs(x)) - always returns 1 or 0
  9. Consider Zero: Zero is neither positive nor negative
  10. Document Usage: Comment when using Sgn in non-obvious ways
Function Purpose Returns Zero Handling
Sgn Get sign -1, 0, or 1 Returns 0
Abs Get magnitude Non-negative number Returns 0
Fix Truncate to integer Integer toward zero Returns 0
Int Round down Integer (floor) Returns 0
Round Round to nearest Rounded number Returns 0
If...Then Conditional logic Any value Requires explicit check

Platform Considerations

Limitations

← Back to Math | View all functions