【问题标题】:What is the reason of error "Floating point exception (core dumped)"错误“浮点异常(核心转储)”的原因是什么
【发布时间】:2017-12-20 14:19:50
【问题描述】:

我正在尝试保存 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 procedure ns2


    【解决方案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) }]
    

    也将您的表达式放在{braces} 中,就像我在上面所做的那样。它允许 Tcl 对表达式进行字节码编译并使您的代码更快。它还可以让您在表达式中安全地放置空格,即使您没有拆分多行,也可以大大提高可读性,并确保在您碰巧使用包含非表达式中的数值。简而言之,这很容易做到,并且可以使您的代码变得更好。


    其他小问题

    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
      

      取决于代码的其余部分是否应该比较来自两种方式的值(但从不与自身),或者只是一种方式。后者的工作量较少,但如果比较不对称(这取决于您要做什么的细节),则可能是错误的。

    【讨论】:

    • 关于循环。我想将变量分配给输出,即$result 用于最近的两个像这样的元组。例如在两次迭代后$result 看起来像这样 {500.1 450 8.0} {378.1 478 9.0}所以我想分配 x1>[lindex $result 0 0] &y1> [lindex $result 0 1] 和 x2>[lindex $result 1 0] &y2>[lindex $result 1 1] 。因此我用 0 初始化了“i”和 "j" 为 1,以便在每次迭代后它将从列表中获取最新的两个元组。 if 在第二个 for 循环中,因为最初列表只有一个元组,因此第二个 for 循环无法分配变量并会抛出错误。
    猜你喜欢
    • 1970-01-01
    • 2021-11-17
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多