C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■91938 / )  Re[16]: C++からVBへの変換
□投稿者/ 魔界の仮面弁士 (2297回)-(2019/08/12(Mon) 12:05:54)
2019/08/12(Mon) 13:21:00 編集(投稿者)

No91934 (えんえん さん) に返信
> 何が間違っていますでしょうか?

『ステップ実行』しましょう。

ループ処理などを一行ずつ実行してみた上で、

  この場所では、この変数に
  こういう値がセットされるはずなのに、
  実際にはこんな値になってしまった
 」
…という点を追跡できれば、どこの翻訳実装に問題があったことが明確になりますよね。


> とりあえず、先に ArraySegmentを使った方法を試してみました。

何か所か間違いがありますが、まずはここ。
 tmpr[m * n_radix + j] = xr * wr - xi * wi;

No91934 のコードでは、上記を
> tmpr.Array(m * n_radix + j) = xr * wr - xi * wi
と翻訳してしまっていますので、ここが大きな間違いです。

たとえば、
 Dim x() As Byte = New Byte(5) {11, 22, 33, 44, 55, 66}
 Dim y As New ArraySegment(Of Byte)(x)
 Dim z As New ArraySegment(Of Byte)(x, 2, 3)
において、「y.Array」や「z.Array」は、配列 x への参照を意味します。
※ Span も似たようなものですが、Span はさらに各要素への参照も持ちます。

なので、x(3) = 100 と代入すれば、z(1) も同様に 44 から 100 へと変化します。

この時、それぞれの要素を列挙すれば
 x は {11, 22, 33, 100, 55, 66} 相当 (y.Array や z.Array も同様)
 y は {11, 22, 33, 100, 55, 66} 相当 (y.Offset は 0、y.Count は 6)
 z は {33, 100, 55} 相当 (z.Offset は 2、z.Count は 3)
となります。
Array / Offset / Count プロパティの 3 セットが、この構造体の肝です。
ここまでは良いでしょうか。


ArraySegment 構造体の場合、値の取得については
 MsgBox( z(i) )
のように書けるのですが、問題は書き込みです。インデクサが ReadOnly なので、
 z(i) = newValue
のようには書けません。(Span 構造体なら可能になるはず)

そのため、オフセット指定の書き込みが必要な場合には、
 z.Array(z.Offset + i) = newValue
のように、Array プロパティと Offset プロパティを併用することになります。
No91934 のコードでは、この点が考慮されていないように見受けられます。


=====

それと、むやみに ByRef を使わないでください。
今回は出力引数が存在しないため、ByRef の出番は一切ありません。

先にも述べましたが、出力引数が必要な場合以外は、値渡しで実装するべきです。



Sub Main()
  Dim x() As Byte = New Byte(3) {&H11, &H22, &HAB, &HCD}
  MsgBox(BitConverter.ToString(x))

  'AsSegment については No91917 を参照
  Test(x.AsSegment())
  MsgBox(BitConverter.ToString(x))

  Test(x.AsSegment(2, 2))
  MsgBox(BitConverter.ToString(x))
End Sub

' a(0) と a(1) の中身を入れ替える処理
' この時、引数 ArraySegment 構造体を ByRef にする必要は無い!
Sub Test(Of T)(ByVal a As ArraySegment(Of T))
  Dim swap() As T = {a(0), a(1)}
  a.Array(a.Offset + 1) = swap(0)
  a.Array(a.Offset + 0) = swap(1)
End Sub


※ 先の No91917 ですが、最後の End Function が誤って End Sub になっていました。
 恐れ入りますが、 End Function に読み替えておいてください。


> Public Sub one_D_FFT(ByRef xr#(), ByRef xi#())
> Private Sub fft(ByVal n%, ByVal theta#, ByRef ar As ArraySegment(Of Double), ByRef ai As ArraySegment(Of Double), ByRef tmpr As ArraySegment(Of Double), ByRef tmpi As ArraySegment(Of Double))

これらについて、メソッド名を分ける必要は無いと思います。オーバーロードで十分ではないでしょうか。
 Public Sub Fft(xr#(), xi#())
 Private Sub Fft(n%, theta#, ar As ArraySegment(Of Double), ar As ArraySegment(Of Double), tmpr As ArraySegment(Of Double), tmpi As ArraySegment(Of Double))


メソッド名を分けるにしても、両者でメソッド名の大文字小文字の使い分けが不揃いな点が気にかかります。
.NET Framework においては一般的に、
  ・クラス名やメソッド名は PascalCase 構文の大文字小文字表記とする。
  ・変数や引数は、camelCase 構文の大文字小文字表記とする。
というのが一般的ですので、この点を意識したコーディングにされることをお奨めします。
https://docs.microsoft.com/ja-jp/dotnet/standard/design-guidelines/naming-guidelines
http://objectclub.jp/community/codingstandard/CodingStdVB.doc
返信 編集キー/


管理者用

- Child Tree -