gpt4 book ai didi

math - tcl中的 float 比较

转载 作者:行者123 更新时间:2023-12-05 00:38:49 28 4
gpt4 key购买 nike

我在计算点和线之间的距离时遇到问题。
存在浮点数计算(比较表达式)问题。因此,我无法知道 $oneextensionFlag 的完美值(value)。请看以下...
我可以知道出了什么问题吗?

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]


}
}

最佳答案

浮点数(在所有语言中,而不仅仅是 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
}

基本上,考虑将点更改为小间隔的数轴:
                0                1
————————————————|————————————————|————————————————


             0-ε 0+ε          1-ε 1+ε
———————————————(—)——————————————(—)———————————————

如何检查您所在的范围,然后遵循该范围。

关于math - tcl中的 float 比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5257707/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com