错误“浮点异常(核心转储)”

时间:2017-07-15 16:51:06

标签: tcl procedure ns2

我正在尝试保存$result的输出proc Inverse2每隔一秒后调度一次(在另一个过程中调用,该过程重新安排为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
        }
    }
}

1 个答案:

答案 0 :(得分:1)

浮点异常可能来自几个不同的事情。一般来说,主要的罪魁祸首是做一些像零除零的事情。但是,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进行字节码编译表达式并使代码更快。它还允许您安全地在表达式中放置空格,这有助于提高可读性,即使您没有拆分多行,并确保您获得(更多!)更好的错误消息,如果您碰巧使用持有a的变量表达式中的非数字值。简而言之,它很容易做到并使您的代码更好。

其他小问题

  1. 您是否希望($now-($now-1))计算除1之外的其他内容?或者至少是一个非常接近1.0的值,假设您在模拟时间内处理浮点数?我认为您v的计算可以安全地简化为直接使用hypot()

  2. 这两个嵌套循环看起来很奇怪:

    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
    

    取决于代码的其余部分是否应该比较来自两种方式的值(但从不与自身相比),或者只是单向循环。后者的工作量较少,但如果比较不对称(这取决于你所做的事情的详细信息)可能是错误的。