2017-07-15 71 views
0

我試圖保存proc Inverse2的輸出$result,它在每一秒鐘後被調度(它在另一個過程中被調用,該過程被重新調度爲1秒,所以Inverse2程序) 我想輸出是{XY現在}並指定變量它最新的兩個實例錯誤「浮點異常(核心轉儲)」的原因是什麼

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

浮點異常可能來自幾個不同的東西。一般來說,主要的罪魁禍首是做一些可怕的事情,比如將零除以零。但是,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通過字節碼編譯表達式並使代碼更快一些。它還可以讓你安全地在表達式中放置空格,即使你沒有分割多行,也可以提高可讀性,並且如果碰巧使用了一個變量來保存非易失性元素,數值在您的表達式中。總之,這很容易做到,並使您的代碼更好。


其他的一些小問題

  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 
    

    取決於是否休息的代碼應該比較來自兩種方式的值(但從來不與自身),或者只是一種方式的輪迴d。後者的工作量較少,但如果比較不對稱(這取決於您所做的細節),則可能會出錯。

+0

關於爲loop.I要分配變量輸出即'$ result'了最新的二元組像this.eg兩次迭代'$後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]。因此我初始化了「i」爲0和「j」加1,這樣在每次迭代之後它將從列表中取出最新的兩個元組。 'if'裏面第二個for循環,因爲最初list只有一個元組,因此second for循環不能分配變量並且會拋出錯誤。 –