错误原因是什么 "Floating point exception (core dumped)"
What is the reason of error "Floating point exception (core dumped)"
我正在尝试保存 proc Inverse2
的输出 $result
每隔一秒安排一次(它在另一个过程中调用,该过程被重新安排 1 秒,这就是 Inverse2 过程的原因)
我想获得 {x y now} 的输出并为最近的两个实例分配变量
x1-> x location at current time (for example at 8.0)
y1-> y location at current time
x2-> x location at (current time+1) (for example at 9.0)
y2-> y location at (current time+1)
并用于进一步计算。
下面是我试过的代码,但我在两次迭代后得到的错误是 Floating point exception (core dumped)
。我哪里做错了?
代码:
set result {}
proc Inverse2 {m} {
set op [open output.tr w]
global result
global ns
set now [$ns now]
lassign [lindex $m 0 2] x1
lassign [lindex $m 0 3] y1
lassign [lindex $m 0 6] d1
lassign [lindex $m 1 2] x2
lassign [lindex $m 1 3] y2
lassign [lindex $m 1 6] d2
lassign [lindex $m 2 2] x3
lassign [lindex $m 2 3] y3
lassign [lindex $m 2 6] d3
set mt {{? ?} {? ?}}
lset mt 0 0 [expr 2*($x1-$x2)]
lset mt 0 1 [expr 2*($y1-$y2)]
lset mt 1 0 [expr 2*($x1-$x3)]
lset mt 1 1 [expr 2*($y1-$y3)]
set const {{?} {?}}
lset const 0 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x2,2)+pow($y2,2)-pow($d2,2))}]
lset const 1 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x3,2)+pow($y3,2)-pow($d3,2))}]
#puts $result "$const"
# puts $result "$mt"
set x [expr {double([lindex [Inverse3 $mt] 0 0] * [lindex $const 0]
+ [lindex [Inverse3 $mt] 0 1] * [lindex $const 1])}]
set y [expr {double([lindex [Inverse3 $mt] 1 0] * [lindex $const 0]
+ [lindex [Inverse3 $mt] 1 1] * [lindex $const 1])}]
lappend result "$x $y $now"
puts $result
for {set i 0} {$i< [llength $result]} {incr i} { #for latest two instances
for {set j 1} {$i< [llength $result]} {incr j} {
set X1 [lindex $result $i 0]
set Y1 [lindex $result $i 1]
if {[llength $result] >1} { #to ensure length of list is greater than 1
set X2 [lindex $result $j 0]
set Y2 [lindex $result $j 1]
set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))]
set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))]
set Xp [expr ($X2+($v*$now*cos($theta)))]
set Yp [expr ($Y2+($v*$now*sin($theta)))]
puts "$Xp $Yp"
}
break
}
}
}
浮点异常可能来自几种不同的情况。一般来说,罪魁祸首是做了一些糟糕的事情,比如用零除以零。但是,Tcl 通常非常擅长确保此类事情不会使您的程序完全崩溃,而只会产生您可以捕获的错误。因此,无论发生什么情况,要么是更棘手的情况之一,要么是由于 ns2 中的 运行 和打开信号浮点错误(Tcl 的标准实现精确地禁用它们以避免可能不必要的致命崩溃)。
如果是后者,将处理从流程中移出到标准 tclsh
是最简单的方法。我们可以更好地保证行为的正确性,因为我们可以更好地控制 FPU 标志等棘手的事情。
但如果是前者……问题应该出在这几行:
set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))]
set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))]
set Xp [expr ($X2+($v*$now*cos($theta)))]
set Yp [expr ($Y2+($v*$now*sin($theta)))]
在那几行中,看起来最可疑的是 theta
. 的计算由于三角函数的周期性,不能正确处理某些象限)但最令人讨厌的是,如果两个连续的位置相同,你在那里有一个除法,它将被零除。鉴于您可以使用 hypot()
,计算角度 目前 最好用 atan2()
计算,因为它可以更好地处理棘手的边缘情况(例如,它没有可怕的无穷大的问题)。试试这个:
set theta [expr { atan2($Y2-$Y1, $X2-$X1) }]
也像我上面那样把你的表达式放在 {
大括号}
中。它允许 Tcl 字节码编译表达式并使您的代码更快一些。它还可以让您安全地在表达式中放置空格,即使您没有拆分多行,这也有助于提高可读性,并确保您在碰巧使用包含非 - 的变量时得到(很多!)更好的错误消息表达式中的数值。简而言之,它很容易做到并且可以使您的代码更好。
其他小问题
您希望 ($now-($now-1))
计算除 1 之外的任何值吗?或者至少一个非常接近 1.0
的值,因为您正在处理模拟时间的浮点数?我认为您对 v
的计算可以安全地简化为直接使用 hypot()
.
这两个嵌套循环看起来很奇怪:
for {set i 0} {$i< [llength $result]} {incr i} {
for {set j 1} {$i< [llength $result]} {incr j} {
我想你要么是想这样做:
for {set i 0} {$i< [llength $result]} {incr i} {
for {set j 0} {$j< [llength $result]} {incr j} {
if {$i == $j} continue; # Skip the diagonal in the comparison matrix
或者这个:
for {set i 0} {$i< [llength $result]} {incr i} {
for {set j [expr {$i + 1}]} {$j< [llength $result]} {incr j} {
# Just the upper triangle of the comparison matrix
取决于代码的其余部分是应该比较双向的值(但从不与自身比较),还是只比较单向的值。后者的工作较少,但如果比较不对称(这取决于您所做的事情的细节),则可能是错误的。
我正在尝试保存 proc Inverse2
的输出 $result
每隔一秒安排一次(它在另一个过程中调用,该过程被重新安排 1 秒,这就是 Inverse2 过程的原因)
我想获得 {x y now} 的输出并为最近的两个实例分配变量
x1-> x location at current time (for example at 8.0)
y1-> y location at current time
x2-> x location at (current time+1) (for example at 9.0)
y2-> y location at (current time+1)
并用于进一步计算。
下面是我试过的代码,但我在两次迭代后得到的错误是 Floating point exception (core dumped)
。我哪里做错了?
代码:
set result {}
proc Inverse2 {m} {
set op [open output.tr w]
global result
global ns
set now [$ns now]
lassign [lindex $m 0 2] x1
lassign [lindex $m 0 3] y1
lassign [lindex $m 0 6] d1
lassign [lindex $m 1 2] x2
lassign [lindex $m 1 3] y2
lassign [lindex $m 1 6] d2
lassign [lindex $m 2 2] x3
lassign [lindex $m 2 3] y3
lassign [lindex $m 2 6] d3
set mt {{? ?} {? ?}}
lset mt 0 0 [expr 2*($x1-$x2)]
lset mt 0 1 [expr 2*($y1-$y2)]
lset mt 1 0 [expr 2*($x1-$x3)]
lset mt 1 1 [expr 2*($y1-$y3)]
set const {{?} {?}}
lset const 0 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x2,2)+pow($y2,2)-pow($d2,2))}]
lset const 1 [expr {(pow($x1,2)+pow($y1,2)-pow($d1,2))-(pow($x3,2)+pow($y3,2)-pow($d3,2))}]
#puts $result "$const"
# puts $result "$mt"
set x [expr {double([lindex [Inverse3 $mt] 0 0] * [lindex $const 0]
+ [lindex [Inverse3 $mt] 0 1] * [lindex $const 1])}]
set y [expr {double([lindex [Inverse3 $mt] 1 0] * [lindex $const 0]
+ [lindex [Inverse3 $mt] 1 1] * [lindex $const 1])}]
lappend result "$x $y $now"
puts $result
for {set i 0} {$i< [llength $result]} {incr i} { #for latest two instances
for {set j 1} {$i< [llength $result]} {incr j} {
set X1 [lindex $result $i 0]
set Y1 [lindex $result $i 1]
if {[llength $result] >1} { #to ensure length of list is greater than 1
set X2 [lindex $result $j 0]
set Y2 [lindex $result $j 1]
set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))]
set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))]
set Xp [expr ($X2+($v*$now*cos($theta)))]
set Yp [expr ($Y2+($v*$now*sin($theta)))]
puts "$Xp $Yp"
}
break
}
}
}
浮点异常可能来自几种不同的情况。一般来说,罪魁祸首是做了一些糟糕的事情,比如用零除以零。但是,Tcl 通常非常擅长确保此类事情不会使您的程序完全崩溃,而只会产生您可以捕获的错误。因此,无论发生什么情况,要么是更棘手的情况之一,要么是由于 ns2 中的 运行 和打开信号浮点错误(Tcl 的标准实现精确地禁用它们以避免可能不必要的致命崩溃)。
如果是后者,将处理从流程中移出到标准 tclsh
是最简单的方法。我们可以更好地保证行为的正确性,因为我们可以更好地控制 FPU 标志等棘手的事情。
但如果是前者……问题应该出在这几行:
set v [expr hypot($X2-$X1,$Y2-$Y1)/ ($now-($now-1))]
set theta [expr acos(($X2-$X1)/(hypot($X2-$X1,$Y2-$Y1)))]
set Xp [expr ($X2+($v*$now*cos($theta)))]
set Yp [expr ($Y2+($v*$now*sin($theta)))]
在那几行中,看起来最可疑的是 theta
. 的计算由于三角函数的周期性,不能正确处理某些象限)但最令人讨厌的是,如果两个连续的位置相同,你在那里有一个除法,它将被零除。鉴于您可以使用 hypot()
,计算角度 目前 最好用 atan2()
计算,因为它可以更好地处理棘手的边缘情况(例如,它没有可怕的无穷大的问题)。试试这个:
set theta [expr { atan2($Y2-$Y1, $X2-$X1) }]
也像我上面那样把你的表达式放在 {
大括号}
中。它允许 Tcl 字节码编译表达式并使您的代码更快一些。它还可以让您安全地在表达式中放置空格,即使您没有拆分多行,这也有助于提高可读性,并确保您在碰巧使用包含非 - 的变量时得到(很多!)更好的错误消息表达式中的数值。简而言之,它很容易做到并且可以使您的代码更好。
其他小问题
您希望
($now-($now-1))
计算除 1 之外的任何值吗?或者至少一个非常接近1.0
的值,因为您正在处理模拟时间的浮点数?我认为您对v
的计算可以安全地简化为直接使用hypot()
.这两个嵌套循环看起来很奇怪:
for {set i 0} {$i< [llength $result]} {incr i} { for {set j 1} {$i< [llength $result]} {incr j} {
我想你要么是想这样做:
for {set i 0} {$i< [llength $result]} {incr i} { for {set j 0} {$j< [llength $result]} {incr j} { if {$i == $j} continue; # Skip the diagonal in the comparison matrix
或者这个:
for {set i 0} {$i< [llength $result]} {incr i} { for {set j [expr {$i + 1}]} {$j< [llength $result]} {incr j} { # Just the upper triangle of the comparison matrix
取决于代码的其余部分是应该比较双向的值(但从不与自身比较),还是只比较单向的值。后者的工作较少,但如果比较不对称(这取决于您所做的事情的细节),则可能是错误的。