Menu

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

open
5
2012-05-28
2012-05-26
No

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.

Discussion

  • 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).

     
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.