Version 16 of eq

Updated 2012-09-21 12:30:14 by RLE

Infix operator for string comparison inside expr. Returns true if its arguments are string-equal.

Its opposite part is ne which returns true if its arguments are not string-equal.

Differs from == in such that its arguments cannot be treated as numerical values, so 1 == 1.0 returns true, but 1 eq 1.0 returns false.

Example:

% expr {"a" eq "b"}
0
% expr {"a" ne "b"}
1

Also comparing text with eq is faster than ==.

AMG: Efficiency is a secondary concern. Correctness comes first. Your program will misbehave, sometimes in non-obvious ways, if you use == when you need eq or vice versa. When you're comparing strings, use eq. When you're comparing numbers, use ==. Numbers can be equivalent yet have different string representations; strings can be different yet have the same numerical representation. "\t1.e0" == "0x001\n". Luckily, in this case the correct thing is also the fast thing.


BC: Which is more efficient - string compare or eq?

AMG: time to the rescue!

proc 1 {a b} {expr {$a eq $b}}
proc 2 {a b} {::tcl::mathop::eq $a $b}
proc 3 {a b} {string compare $a $b}
proc 4 {a b} {string equal $a $b}
set a "\t1.e0"
set b "0x001\n"
time {1 $a $b} 1000000 ;# 1.633135 microseconds per iteration
time {2 $a $b} 1000000 ;# 1.619685 microseconds per iteration
time {3 $a $b} 1000000 ;# 1.618814 microseconds per iteration
time {4 $a $b} 1000000 ;# 1.612457 microseconds per iteration

It's a wash; the difference is nanoseconds. The actual eq operator (2) takes about the same amount of time as string compare (3). Embedding eq into an expr adds some overhead, which you pay for anyway if you're using if, while, for, or other math and logic.

string compare is closer to ne in behavior; both return 0 when the strings are equal. string equal is the closest command to eq. string compare and string equal both have options that eq and ne do not.


DAB: The timings on this page don't take the "if" condition into account. "if" is automatically calling "expr", so "if{string equal}" is calling one extra command.

Code:

proc 1 {a b} {if {$a eq $b} {return 1}}
proc 2 {a b} {if {[string equal $a $b]} {return 1}}
set a "\t1.e0"
set b "0x001\n"
puts [time {1 $a $b} 1000000] ;# 1.101801 microseconds per iteration
puts [time {2 $a $b} 1000000] ;# 1.230454 microseconds per iteration

Using this pattern, "eq" is about 10% faster.


ko - 2012-09-21 11:33:39

A simple compare between eq with == and ne with != Difference is about 20% in speed

set i 0

set start_time [clock clicks -milliseconds]
for { set i 1 } { $i <= 1000000 } { incr i } {

        set var "waarde_$i"

        if {$var eq "waarde_nr_"} {
                puts stdout ""
        }
}

set current_time [clock clicks -milliseconds]
set diff_time1 [expr "$current_time - $start_time"]

puts stdout "Eq command takes $diff_time1 ms"


# #############################################
set i 0

set start_time [clock clicks -milliseconds]
for { set i 1 } { $i <= 1000000 } { incr i } {

        set var "waarde_$i"

        if {$var == "waarde_nr_"} {
                puts stdout ""
        }
}

set current_time [clock clicks -milliseconds]
set diff_time2 [expr "$current_time - $start_time"]

puts stdout "== command takes $diff_time2 ms"
puts stdout "[expr (($diff_time2 - $diff_time1)/($diff_time2 * 1.0)) * 100] %"

# #############################################

set start_time [clock clicks -milliseconds]
for { set i 1 } { $i <= 1000000 } { incr i } {

        set var "waarde_$i"

        if {$var ne "waarde_nr_"} {
                
        }
}

set current_time [clock clicks -milliseconds]
set diff_time3 [expr "$current_time - $start_time"]
puts stdout "Ne command takes $diff_time3 ms"


# #############################################
set i 0

set start_time [clock clicks -milliseconds]
for { set i 1 } { $i <= 1000000 } { incr i } {

        set var "waarde_$i"

        if {$var != "waarde_nr_"} {
                
        }
}

set current_time [clock clicks -milliseconds]
set diff_time4 [expr "$current_time - $start_time"]

puts stdout "!= command takes $diff_time4 ms"
puts stdout "[expr (($diff_time4 - $diff_time3)/($diff_time4 * 1.0)) * 100] %"

Output is:

Eq command takes 1037 ms
== command takes 1301 ms
20.2920830131 %
Ne command takes 1011 ms
!= command takes 1291 ms
21.6886134779 %