[英]Nested “if” (AKA “switch”) in Smalltalk (Pharo)
我需要用一些值填充矩陣(存儲為數組數組)。 對於簡單的擴散問題,矩陣是雅可比矩陣,看起來像這樣:
J(1,1) = 1, J(N,N)=0
並且對於1<n<N
:
J(n,n) = -2k/dx^2 - 2*c(n)
J(n,n-1)=J(n,n+1) = k/dx^2
其余的矩陣條目是零。
到目前為止,我有這種怪異:
(1 to: c size) collect: [ :n |
(1 to: c size) collect: [ :m |
n = 1 | (n = c size)
ifTrue: [ m = n ifTrue: [ 1.0 ] ifFalse: [ 0.0 ] ]
ifFalse: [ m = n
ifTrue: [ -2.0 * k / dx squared - (2.0 * (c at: n)) ]
ifFalse: [ m = (n-1) | (m = (n+1))
ifTrue: [ k / dx squared ]
ifFalse: [ 0.0 ] ] ]
] ]
注意嵌套的“if-statements”(Smalltalk等價物)。 這有效。 但是,是否有更優雅的方式做同樣的事情? 現在看來,這是不可讀的。
n := c size.
Matrix
new: n
tabulate: [:i :j | self jacobianAtRow: i column: j]
哪里
jacobianAtRow: i column: j
n := c size.
(i = 1 or: [i = n]) ifTrue: [^j = i ifTrue: [1.0] ifFalse [0.0]].
j = i ifTrue: [^-2.0 * k / dx squared - (2.0 * (c at: i))].
(j = (i - 1) or: [j = (i + 1)]) ifTrue: [^k / dx squared].
^0.0
基本上,一般的想法是這樣的:每當你找到嵌套的ifs時,將該段代碼單獨分解為一個方法,並將嵌套轉換為類似於case的枚舉,它會盡可能地返回一個值。
為了便於閱讀,我會考慮犧牲額外的O(n)
時間並完全避免IF(這使得它更快......)。
J(N,N) = 0
J(1,1) = 1
//and for 1<n<N:
J(n,n) = Y(n)
J(n,m-1) = J(n,m+1) = X
這告訴我的是整個矩陣看起來像這樣
( 1 X 0 0 0 )
( X Y X 0 0 )
( 0 X Y X 0 )
( 0 0 X Y X )
( 0 0 0 X 0 )
這意味着我可以用零創建整個矩陣,然后改變對角線和相鄰的對角線。
jNM := [ k / dx squared ].
jNN := [ :n | -2.0 * k / dx squared - (2.0 * (c at: n)) ].
n := c size.
m := Matrix
new: n
tabulate: [:i :j | 0 ].
(1 to: n - 1) do: [ :i |
m at: i at: i put: (jNN value: i).
m at: i + 1 at: i put: jnM value.
m at: i at: i + 1 put: jnM value.
].
m at: 1 at: 1 put: 1.
注意:我不熟悉這背后的數學,但J(n,m-1)
的值對我來說似乎是一個常數。
注2:我將值放在i + 1
指數處,因為我從位置1;1
開始,但你可以從相反的方向開始並擁有i-1
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.