C#の複素数型は、↓こちらを参照ください。
Swift の記事ですが、今回の動作検証は Windows PC で行いました。
Intel N97 Processor, LPDDR5 RAM 12GB
Windows11 Pro 64bit 24H2 (26100.2161)
C# Compiler version 4.11.0-3.24460.3 (5649376e)
Swift version 5.9.2 (swift-5.9.2-RELEASE)
当初の Swift にはComplex
型 はありませんでしたが、2019年12月にサポートされました。ただし、Complex
型を使う場合は、Swift Numerics
パッケージを追加する必要があります。
import PackageDescription
let package = Package(
name: "complex",
dependencies: [
.package(url: "https://github.com/apple/swift-numerics", from: "1.0.2")
],
targets: [
.executableTarget(
name: "complex",
dependencies: [
.product(name: "Numerics", package: "swift-numerics")
]),
]
)
精度 C# vs Swift
冒頭の記事のコードを流用させていただきました。
using System.Numerics;
Complex c = new Complex(0, 1);
Console.WriteLine(Complex.Multiply(c, c));
Console.WriteLine(Complex.Pow(c, 2));
Console.WriteLine(Complex.Sqrt(c));
Console.WriteLine(Complex.Pow(c, 0.5));
Console.WriteLine(Complex.Pow(c, c));
import Numerics
let c = Complex(0, 1)
print(c * c)
print(Complex.pow(c, 2))
print(Complex.sqrt(c))
print(Complex.pow(c, Complex(0.5, 0)))
print(Complex.pow(c, c))
<-1; 0>
<-1; 1.2246467991473532E-16>
<0.7071067811865476; 0.7071067811865475>
<0.7071067811865476; 0.7071067811865476>
<0.20787957635076193; 0>
(-1.0, 0.0)
(-1.0, 1.2246467991473532e-16)
(0.7071067811865476, 0.7071067811865475)
(0.7071067811865476, 0.7071067811865475)
(0.20787957635076193, 0.0)
計算精度は、イーブンでした。
性能 C# vs Swift
冒頭の記事のマンデルブロ集合
のコードを流用させていただきました。
10回描画の平均値(コンソール出力も含めた処理時間)
using System.Numerics;
using System.Diagnostics;
long MandelbrotSet()
{
Stopwatch sw = Stopwatch.StartNew();
for (double y = -1.25d; y <= 1.25d; y += 2.5d / 24.0d)
{
for (double x = -2.0d; x <= 0.5d; x += 2.5d / 64.0d)
{
Complex z = new Complex(0, 0);
Complex c = new Complex(x, y);
for (int n = 0; n < 256; n++)
{
z = Complex.Pow(z, 2);
z = Complex.Add(z, c);
if (z.Magnitude > 2)
{
Console.Write(".");
break;
}
if (n == 255)
{
Console.Write("*");
}
}
}
Console.WriteLine("");
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
long total = 0;
List<long> results = new List<long>();
for (int n = 0; n < 10; n++)
{
long result = MandelbrotSet();
total += result;
results.Add(result);
}
results.Sort();
foreach (var r in results)
{
Console.WriteLine(r);
}
Console.WriteLine((double)total / (double)results.Count);
import Foundation
import Numerics
func MandelbrotSet() -> Double {
let sw = Stopwatch.startNow()
for y in stride(from: -1.25, through: 1.25, by: 2.5 / 24.0) {
for x in stride(from: -2.0, through: 0.5, by: 2.5 / 64.0) {
var z = Complex(0, 0)
let c = Complex(x, y)
for n in 0 ..< 256 {
z = Complex.pow(z, 2)
z += c
if (z.magnitude > 2) {
print(".", terminator: "")
break
}
if (n == 255) {
print("*", terminator: "")
}
}
}
print()
}
sw.stop()
return sw.elapsedMilliseconds
}
var total: Double = 0;
var results: [Double] = []
for _ in 0 ..< 10 {
let result = MandelbrotSet()
total += result
results.append(result)
}
results.sort()
for r in results {
print(r)
}
print(total / Double(results.count))
.................................................................
.................................................................
.................................................................
.................................................................
................................................*................
..............................................*****..............
..........................................*.*********.*..........
.......................................*********************.....
...................................*************************.....
..................................****************************...
......................********...*****************************...
....................************.****************************....
......*........*******************************************.......
....................************.****************************....
......................********...*****************************...
..................................****************************...
...................................*************************.....
.......................................*********************.....
..........................................*.*********.*..........
..............................................*****..............
................................................*................
.................................................................
.................................................................
.................................................................
.................................................................
57
57
58
58
58
59
59
63
64
66
59.9
49.999237060546875
55.00030517578125
59.00001525878906
59.99946594238281
59.99946594238281
59.99946594238281
62.999725341796875
62.999725341796875
63.00163269042969
63.00163269042969
59.600067138671875
10回の平均値は 59.9ms と 59.6ms で、こちらもほぼイーブンです。(実行する度に、10〜20ミリ秒のブレがある)
どちらの結果もミリ秒
単位ですが、C#は long型 、Swiftは Double型と違いがあります。そもそも正しいベンチマークになっていないのかも?
Swiftで使用した Stopwatch型はこちら
を参照。
参考
実は、Complex型の何が便利なのか理解できていません。勉強不足ですみません。
古い記事ですが、ネットで見つけたサイトを紹介します。
- 2016/7/13 (SwiftにまだComplex型が無かった頃)
- 2019/11/12 (SwiftにComplex型がサポートされた後)
- 日本語サイト
以上