Math tcl中的浮点数比较

Math tcl中的浮点数比较,math,floating-point,tcl,Math,Floating Point,Tcl,我在计算点和线之间的距离时遇到问题。 存在浮点数计算(比较表达式)问题。因此,我无法知道$onextensionFlag的完美值。请看下面。。。 我能知道怎么了吗 proc calculateDistanceToLinefrompoint {P line} { # solution based on FAQ 1.02 on comp.graphics.algorithms # L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 ) # (Ay-Cy)(Bx-Ax)-(Ax-

我在计算点和线之间的距离时遇到问题。 存在浮点数计算(比较表达式)问题。因此,我无法知道$onextensionFlag的完美值。请看下面。。。 我能知道怎么了吗

proc calculateDistanceToLinefrompoint {P line} {
# solution based on FAQ 1.02 on comp.graphics.algorithms
# L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )

#     (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
# s = -----------------------------
#                 L^2
# dist = |s|*L # =>
#        | (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) |
# dist = ---------------------------------
#                       L
# (Ay-Cy)(Ay-By)-(Ax-Cx)(Bx-Ax)
# r = -----------------------------
                # L^2
# r=0      P = A
# r=1      P = B
# r<0      P is on the backward extension of AB
# r>1      P is on the forward extension of AB
# 0<=r<=1    P is interior to AB

set ret 0
set Ax [lindex $line 0 0]
set Ay [lindex $line 0 1]
set Az [lindex $line 0 2]

set Bx [lindex $line 1 0]
set By [lindex $line 1 1]
set Bz [lindex $line 1 2]

set Cx [lindex $P 0]
set Cy [lindex $P 1]
set Cz [lindex $P 2]

if {$Ax==$Bx && $Ay==$By && $Az==$Bz} {
    set ret [list [GetDistanceBetweenTwoPoints $P [lindex $line 0]] 1] 
} else {
    set L [expr {sqrt(pow($Bx-$Ax,2) + pow($By-$Ay,2) + pow($Bz-$Az,2))}]
    #puts "L=$L"
    set d_val [expr {($Ay-$Cy)*($Bx-$Ax)-($Ax-$Cx)*($By-$Ay)-($Az-$Bz)*($Az-$Cz)}]
    set n_rval [expr {$d_val / pow($L,2)}]
    set n_rval [format "%0.3f" $n_rval]

    if { 0 < $n_rval && $n_rval < 1} {
        set onextensionFlag 0;# inside clipping area
    } elseif {$n_rval == 0 || $n_rval == 1} {
        set onextensionFlag 1 ;# inside clipping area (but on point)
    } elseif { $n_rval > 1 || $n_rval < 0 } {
        set onextensionFlag 2 ;# outside clipping area
    } else {
        set onextensionFlag 3 ;# consider inside clipping area
    }

    set ret [list [expr {abs($d_val) / $L}] $onextensionFlag $n_rval]


     }
    }
proc calculatedInstanceTolieFrompoint{P line}{
#基于常见问题解答1.02关于comp.graphics.algorithms的解决方案
#L=sqrt((Bx Ax)^2+(按日期)^2)
#(Ay-Cy)(Bx-Ax)-(Ax-Cx)(通过Ay)
#s=-----------------------------
#L^2
#距离=| s |*L=>
#|(Ay-Cy)(Bx-Ax)-(Ax-Cx)(通过Ay)|
#距离=---------------------------------
#L
#(Ay-Cy)(Ay-By)-(Ax-Cx)(Bx-Ax)
#r=-----------------------------
#L^2
#r=0 P=A
#r=1 P=B
#r1 P位于AB的向前延伸处
#0浮点数(在所有语言中,而不仅仅是Tcl)表示的大多数数字都有点不精确。因此,通常不应该对它们进行相等性比较,因为这是不太可能的。相反,您应该检查这两个值是否在彼此的一定范围内(该量称为epsilon,并考虑到浮点计算中存在小错误)

在代码中,您可以编写以下代码:

set epsilon 0.001; # Small, but non-zero
if { $epsilon < $n_rval && $n_rval < 1-$epsilon} {
    set onextensionFlag 0;# inside clipping area
} elseif {abs($n_rval) < $epsilon || abs(1-$n_rval) < $epsilon} {
    set onextensionFlag 1 ;# inside clipping area (but on point)
} elseif { $n_rval >= 1+$epsilon || $n_rval <= -$epsilon } {
    set onextensionFlag 2 ;# outside clipping area
} else {
    set onextensionFlag 3 ;# consider inside clipping area
}


如何检查您所处的范围,然后再进行检查。

谢谢。这是我一直在寻找的。这对我来说是一个很好的教训。此外,在IEEE浮点(Tcl使用)中,精确的数字是达到相当合理大小的整数。但不是无限大的;双精度浮点有固定的位数。
                0                1
————————————————|————————————————|————————————————
             0-ε 0+ε          1-ε 1+ε
———————————————(—)——————————————(—)———————————————