#619 New function in "expr": sgn()


There are functions double, int, floor and ceil for rounding floating point values in various mode, but e.g. floor($num) and ceil($num) are equivalent with round($num -+ 0.5). But the signum function can be implemented only with longer constructs.


  • Szabó László Zoltán

    I would take back my example: "floor($num) and ceil($num) are equivalent with round($num -+ 0.5)" it is not right.
    But not this is the point now.

  • Donal K. Fellows

    • summary: New funcion in "expr": sgn() --> New function in "expr": sgn()
  • Donal K. Fellows

    Here's a complete workaround (modulo ensuring that $x is numeric and handling NaN):

    proc tcl::mathfunc::sgn {x} {
    expr {$x < 0 ? -1 : $x > 0 ? 1 : 0}

    The only question is whether Tcl should provide such a thing by default.

  • Twylite

    Twylite - 2012-05-28

    is sgn() meant to be "sign()" as in DKF's example, or is it meant to be "round to a number of significant digits" as discussed below?

    In Excel for example, =FLOOR(1.134, 0.01) rounds 1.134 down to the nearest multiple of 0.01, giving 1.13. Similarly =FLOOR(1.5, 0.4) gives 1.2. The =ROUND() function rounds to a number of digits, e.g. =ROUND(1.135, 2) gives 1.14.

    The Excel functions combine a mathematical operation and an output formatting operation. The result of =FLOOR(1.134, 0.01) may not be accurately represented by a float or a double, so the floating point value is truncated for display purposes.

    Rounding to a significant number of digits (as in =ROUND) as opposed to an exact significance (as in =FLOOR) is quite easy in Tcl:

    proc round {d sgn} { format %0.${sgn}f $d }

    Computing and displaying floor or ceiling to a specific precision is more complicated:

    proc floor {d sgn} {
    set prec [expr { int(ceil(-log($sgn)/log(10))) }]
    format %0.${prec}f [expr { floor($d / $sgn) * $sgn }]

    A compromise may be to extend round, floor and ceil to take an optional second parameter (significance), and implement equivalent to:

    proc round {d {sgn 1}} { expr { round($d / $sgn) * $sgn } }
    proc floor {d {sgn 1}} { expr { floor($d / $sgn) * $sgn } }

    This gives a mathematically accurate answer (within the constraints of floating point arithmetic), but does not attempt to format/truncate the output. This would be appropriate behaviour for [expr] in my opinion (but including formatting behaviour would not be appropriate).


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks