複素数
Posted feedbacks - Flatten
Nested Hidden1 2 3 4 5 6 7 8 9 10 | > (+ #C(3 1) #C(4 -1))
7
> (- #C(5 -9) #C(2 6))
#C(3 -15)
> (* #C(5 3) #C(5 8))
#C(1 55)
> (/ #C(9 -7) #C(9 -3))
#C(17/15 -2/5)
> (abs #C(2 3))
3.6055512
|
Common LispやSchemeだと問題になりませんね、これ。
1 2 3 4 5 6 7 8 9 10 11 | Welcome to MzScheme v4.0 [cgc], Copyright (c) 2004-2008 PLT Scheme Inc.
> (+ 3+i 4-i)
7
> (- 5-9i 2+6i)
3-15i
> (* 5+3i 5+8i)
1+55i
> (/ 9-7i 9-3i)
17/15-2/5i
> (magnitude 2+3i)
3.6055512754639896
|
実行結果:
7.0
3.0 - 15.0i
1.0 + 55.0i
1.1333333333333333 - 0.4i
3.605551275463989
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | object Complex {
implicit def complex2richComplex(c: Complex) = new RichComplex(c)
class RichComplex(val self: Complex) extends Proxy {
def abs = self match {
case Complex(re, im) => Math.sqrt(re*re + im*im)
}
}
implicit def int2Complex (n: Int ): Complex = Complex(n, 0)
implicit def double2Complex(n: Double): Complex = Complex(n, 0)
val i = Complex(0, 1)
}
case class Complex(real: Double, imag: Double) {
// +(a + bi) = (a + bi)
def unary_+ = this
// -(a + bi) = (-a - bi)
def unary_- = Complex(-real, -imag)
// (a + bi) + (c + di) = (a + c) + (b + d)i
def + (that: Complex) = Complex(this.real + that.real, this.imag + that.imag)
// (a + bi) - (c + di) = (a - c) + (b - d)i
def - (that: Complex) = Complex(this.real - that.real, this.imag - that.imag)
// (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
def * (that: Complex) = {
val Complex(a, b) = this
val Complex(c, d) = that
Complex(a*c - b*d, b*c + a*d)
}
// (a + bi) / (c + di) = (ac + bd) / (c^2 + d^2) + (bc - ad) / (c^2 + d^2)
def / (that: Complex) = {
val Complex(a, b) = this
val Complex(c, d) = that
val deno = c*c + d*d
Complex((a*c + b*d) / deno, (b*c - a*d) / deno)
}
override def toString = this match {
case Complex(re, 0) => re.toString
case Complex( 0, 1) => "i"
case Complex( 0, -1) => "-i"
case Complex( 0, im) => im.toString + "i"
case Complex(re, 1) => re.toString + " + i"
case Complex(re, -1) => re.toString + " - i"
case Complex(re, im) if im >= 0 => re.toString + " + " + im.toString + "i"
case Complex(re, im) => re.toString + " - " + im.abs.toString + "i"
}
}
object Doukaku247 {
import Complex._
def main(args: Array[String]) {
println( (3 + i ) + (4 - i ) )
println( (5 - 9*i) - (2 + 6*i) )
println( (5 + 3*i) * (5 + 8*i) )
println( (9 - 7*i) / (9 - 3*i) )
println( (2 + 3*i).abs )
}
}
|
Rでは組み込みです。
1 2 3 4 5 6 7 8 9 10 | > ( 3 + 1i ) + ( 4 - 1i )
[1] 7+0i
> ( 5 - 9i ) - ( 2 + 6i )
[1] 3-15i
> ( 5 + 3i ) * ( 5 + 8i )
[1] 1+55i
> ( 9 - 7i ) / ( 9 - 3i )
[1] 1.133333-0.4i
> abs(2 + 3i)
[1] 3.605551
|
1 2 3 4 5 6 7 8 9 10 | >>> (3 + 1j) + (4 - 1j)
(7+0j)
>>> (5 - 9j) - (2 - 6j)
(3-3j)
>>> (5 + 3j) * (5 + 8j)
(1+55j)
>>> (9 - 7j) / (9 - 3j)
(1.1333333333333333-0.40000000000000002j)
>>> abs(2 + 3j)
3.6055512754639896
|
Math::Complexをつかってやってみました。 もう少しきれいにかけると思いますが、 とりあえずわかりやすいように上で沢山の変数を宣言してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | use strict;
use warnings;
use Math::Complex;
my $kasan_a = 3 + i;
my $kasan_b = 4 - i;
my $gensan_a = 5 - 9*i;
my $gensan_b = 2 + 6*i;
my $jyousan_a = 5 + 3*i;
my $jyousan_b = 5 + 8*i;
my $jyosan_a = 9 - 7*i;
my $jyosan_b = 9 - 3*i;
my $zettai = 2 + 3*i;
sub Complex_add{
my $a = $_[0];
my $b = $_[1];
print "$a + $b =",$a+$b,"\n";
}
sub Complex_minus{
my $a = $_[0];
my $b = $_[1];
print "$a - $b =",$a-$b,"\n";
}
sub Complex_times{
my $a = $_[0];
my $b = $_[1];
print "$a * $b =",$a*$b,"\n";
}
sub Complex_divide{
my $a = $_[0];
my $b = $_[1];
print "$a / $b =",$a/$b,"\n";
}
sub Complex_abs{
my $a = $_[0];
print "| $a | =",abs($a),"\n";
}
Complex_add($kasan_a,$kasan_b);
Complex_minus($gensan_a,$gensan_b);
Complex_times($jyousan_a,$jyousan_b);
Complex_divide($jyosan_a,$jyosan_b);
Complex_abs($zettai);
|
Jakarta Commons Math を使ってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import org.apache.commons.math.complex.Complex;
import static org.apache.commons.math.complex.ComplexFormat.*;
public class Sample247 {
public static Complex $(double real, double imaginary) {
return new Complex(real, imaginary);
}
public static void main(String[] args) {
System.out.println(formatComplex(
$(3, 1).add($(4, -1))
));
System.out.println(formatComplex(
$(5, -9).subtract($(2, 6))
));
System.out.println(formatComplex(
$(5, 3).multiply($(5, 8))
));
System.out.println(formatComplex(
$(9, -7).divide($(9, -3))
));
System.out.println($(2, 3).abs());
}
}
|
深くは考えず、FORTRAN でやってみました☆ ( 7.0000000 , 0.0000000 ) ( 3.0000000 , -15.000000 ) ( 1.0000000 , 55.000000 ) ( 1.1333333 ,-0.40000001 ) 3.6055512
1 2 3 4 5 6 | print *, ( 3, 1) + ( 4,-1)
print *, ( 5,-9) - ( 2, 6)
print *, ( 5, 3) * ( 5, 8)
print *, ( 9,-7) / ( 9,-3)
print *, abs(( 2, 3))
end
|
calc(apcalc)で。
see: Calc - C-style arbitrary precision calculator
1 2 3 4 5 6 7 8 9 10 | $ calc '( 3 + 1i ) + ( 4 - 1i )'
7
$ calc '( 5 - 9i ) - ( 2 + 6i )'
3-15i
$ calc '( 5 + 3i ) * ( 5 + 8i )'
1+55i
$ calc '( 9 - 7i ) / ( 9 - 3i )'
~1.13333333333333333333-0.4i
$ calc 'abs( 2 + 3i )'
3.60555127546398929312
|
実行結果: (3,1)+(4,-1)=(7,0) (5,-9)-(2,6)=(3,-15) (5,3)*(5,8)=(1,55) (9,-7)/(9,-3)=(1.13333,-0.4) |(2,3)|=3.60555
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include <complex>
#include <iostream>
using namespace std;
int main(){
complex<double> dc1(3.0, 1);
complex<double> dc2(4.0,-1);
complex<double> dc3(5.0,-9);
complex<double> dc4(2.0, 6);
complex<double> dc5(5.0, 3);
complex<double> dc6(5.0, 8);
complex<double> dc7(9.0,-7);
complex<double> dc8(9.0,-3);
complex<double> dc9(2.0, 3);
cout << dc1 << '+' << dc2 << '=';
cout << dc1 + dc2 << "\n";
cout << dc3 << '-' << dc4 << '=';
cout << dc3 - dc4 << "\n";
cout << dc5 << '*' << dc6 << '=';
cout << dc5 * dc6 << "\n";
cout << dc7 << '/' << dc8 << '=';
cout << dc7 / dc8 << "\n";
cout << '|' << dc9 << "|=";
cout << abs(dc9) << endl;
}
|
実行結果をもう一度 (3,1)+(4,-1)=(7,0) (5,-9)-(2,6)=(3,-15) (5,3)*(5,8)=(1,55) (9,-7)/(9,-3)=(1.13333,-0.4) |(2,3)|=3.60555
J言語では複素数 a + bi を ajb で表現します。
1 2 3 4 5 6 7 8 9 10 | 3j1 + 4j_1
7
5j_9 - 2j6
3j_15
5j3 * 5j8
1j55
9j_7 % 9j_3
1.13333j_0.4
| 2j3
3.60555
|
頑張ってみました。 正直、めんどかったです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | using System;
class P
{
static void Main()
{
Complex a = new Complex(3, 1);
Complex b = new Complex(4, -1);
Complex c = new Complex(5, -9);
Complex d = new Complex(2, 6);
Complex e = new Complex(5, 3);
Complex f = new Complex(5, 8);
Complex g = new Complex(9, -7);
Complex h = new Complex(9, -3);
Complex i = new Complex(2, 3);
Console.WriteLine("({0}) + ({1}) = {2}", a, b, a + b);
Console.WriteLine("({0}) - ({1}) = {2}", c, d, c - d);
Console.WriteLine("({0}) * ({1}) = {2}", e, f, e * f);
Console.WriteLine("({0}) / ({1}) = {2}", g, h, g / h);
Console.WriteLine("|{0}| = {1}", i, i.Abs);
}
}
class Complex
{
protected double re;
protected double im;
protected double abs;
protected double arg;
protected static Complex IUnit = new Complex(0, 1);
public double Re
{
set
{
this.re = value;
this.abs = Math.Sqrt(this.re * this.re + this.im * this.im);
if (this.abs == 0.0)
this.arg = 0;
else
this.arg = Math.Atan2(im, re) * 180 / Math.PI;
}
get { return this.re; }
}
public double Im
{
set
{
this.im = value;
this.abs = Math.Sqrt(this.re * this.re + this.im * this.im);
if (this.abs == 0.0)
this.arg = 0;
else
this.arg = Math.Atan2(im, re) * 180 / Math.PI;
}
get { return this.im; }
}
public double Abs
{
set
{
this.abs = Math.Abs(value);
this.im = abs * Math.Sin(arg * Math.PI / 180);
this.re = abs * Math.Cos(arg * Math.PI / 180);
}
get { return this.abs; }
}
public double Arg
{
set
{
this.arg = value;
this.im = abs * Math.Sin(arg * Math.PI / 180);
this.re = abs * Math.Cos(arg * Math.PI / 180);
}
get { return this.arg; }
}
public static Complex I
{
get { return IUnit; }
}
public Complex() : this(0, 0) { }
public Complex(double a, double b)
{
re = a;
Im = b;
}
public string MyToString(int n)
{
string str = "";
double x = Math.Pow(10.0, n);
double r = Math.Floor(re * x) / x;
double i = Math.Floor(im * x) / x;
if (r != 0)
{
str += r;
if (i > 0)
{
if (i == 1) str += " + i";
else str += " + " + i + "i";
}
else if (i < 0)
{
if (i == -1) str += " - i";
else str += " - " + (-i) + "i";
}
}
else
{
if (i > 0)
{
if (i == 1) str += "i";
else str += i + "i";
}
else if (i < 0)
{
if (i == -1) str += "-i";
else str += "-" + (-i) + "i";
}
}
return str;
}
public static Complex FromArgAbs(double arg, double abs)
{
return new Complex(abs * Math.Cos(arg * Math.PI / 180), abs * Math.Sin(arg * Math.PI / 180));
}
public static Complex Sqrt(Complex x)
{
return Complex.FromArgAbs(x.arg / 2, Math.Sqrt(x.abs));
}
public static Complex PowRatio(Complex x, int num, int den)
{
Complex y = x ^ num;
return Complex.FromArgAbs(y.arg / den, Math.Pow(y.abs, 1.0 / den));
}
public static Complex operator -(Complex x)
{
return (-1) * x;
}
public static Complex operator +(Complex x)
{
return x;
}
public static Complex operator ~(Complex x)
{
return new Complex(x.re, -x.im);
}
public static Complex operator ^(Complex x, int n)
{
if (n > 0)
{
if (n == 1) return x;
Complex z = 1;
return (z ^ (n >> 1)) * (z ^ ((n & 1) + (n >> 1)));
}
else if (n == 0)
return 1;
else
return (1 / x) ^ (-n);
}
public static Complex operator +(Complex x, Complex y)
{
return new Complex(x.re + y.re, x.im + y.im);
}
public static Complex operator -(Complex x, Complex y)
{
return new Complex(x.re - y.re, x.im - y.im);
}
public static Complex operator *(Complex x, Complex y)
{
return Complex.FromArgAbs(x.arg + y.arg, x.abs * y.abs);
}
public static Complex operator /(Complex x, Complex y)
{
return Complex.FromArgAbs(x.arg - y.arg, x.abs / y.abs);
}
public static bool operator ==(Complex x, Complex y)
{
return (x.re == y.re && x.im == y.im);
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
public static implicit operator Complex(double x)
{
return new Complex(x, 0);
}
public static explicit operator Complex(int x)
{
return new Complex(x, 0);
}
public override bool Equals(object o)
{
if (o is Complex)
return this == (Complex)o;
else
return false;
}
public override int GetHashCode()
{
return (re + im).GetHashCode() ^ (re - im).GetHashCode();
}
public override string ToString()
{
return MyToString(4);
}
}
|
Data.Complexを使いました。
1 2 3 4 5 6 7 8 9 10 | import Data.Complex
main = putStrLn $ unlines $ map show
[
(3 :+ 1) + (4 :+ (-1))
,(5 :+ (-9)) - (2 :+ 6)
,(5 :+ 3) * (5 :+ 8)
,(9 :+ (-7)) / (4 :+ (-3))
,abs (2 :+ 3)
]
|
Cでも、C99から複素数演算が導入されました。こんな風になります。
$ gcc -std=c99 t.c -lm && ./a.out (3 + 1i) + (4 - 1i) = (7 + 0i) (5 - 9i) - (2 + 6i) = (3 - 15i) (5 + 3i) * (5 + 8i) = (1 + 55i) (9 - 7i) / (9 - 3i) = (1.13333 - 0.4i) |2 + 3i| = 3.60555
ここでは、FreeBSD 7.1付属gcc 4.2.1を使いました。
記法がアレなのは仕方ありませんが、printf/scanf系書式での対応がないのは残念です。というより面倒です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | $ cat t.c
#include <stdio.h>
#include <complex.h>
#include <math.h>
void print_complex(double complex c)
{
double i = cimag(c);
printf("%g %c %gi",
creal(c),
i >= 0. ? '+'
: '-',
fabs(i));
}
void print_expression(double complex lhs, char ope, double complex rhs, double complex result)
{
putchar('(');
print_complex(lhs);
printf(") %c (", ope);
print_complex(rhs);
printf(") = (");
print_complex(result);
putchar(')');
putchar('\n');
}
int main()
{
double complex al = 3 + I;
double complex ar = 4 - I;
double complex sl = 5 - 9 * I;
double complex sr = 2 + 6 * I;
double complex pl = 5 + 3 * I;
double complex pr = 5 + 8 * I;
double complex dl = 9 - 7 * I;
double complex dr = 9 - 3 * I;
double complex bs = 2 + 3 * I;
double complex a = al + ar;
double complex s = sl - sr;
double complex p = pl * pr;
double complex d = dl / dr;
double b = cabs(bs);
print_expression(al, '+', ar, a);
print_expression(sl, '-', sr, s);
print_expression(pl, '*', pr, p);
print_expression(dl, '/', dr, d);
putchar('|');
print_complex(bs);
printf("| = %g\n", b);
}
|
まさかのExcelです。Excel VBAではありません。いつのバージョンからなのか知りませんが、ワークシート関数として複素数関係のものが揃っています。以下のコードを適当なところに貼り付けてみてください。
Excelでの複素数の扱い方はいたって単純、"1+3i"のような文字列です(虚部のない実数を演算に混ぜることは可能です)。そのままでは、書式指定でも単に文字列として扱われるので、面倒です。
以下余談。Word/Excelでは、今まで自分が欲しいと思った機能が搭載されていなかった試しがありません。さすが最重量級だけのことはあります。というかあんな機能満載では大半の機能は見つけられないし、見つけても使いこなせませんって。
1 2 3 4 5 | =IMSUM("3+i", "4-i")
=IMSUB("5-9i", "2+6i")
=IMPRODUCT("5+3i", "5+8i")
=IMDIV("9-7i", "9-3i")
=IMABS("2+3i")
|
Squeak Smalltalk では複素数は組み込みです。リテラルはなく、整数にメッセージ i を送信することで対応する純虚数値を得るしくみになっています。
1 2 3 4 5 6 | ( 3 + 1i ) + ( 4 - 1i ) "=> 7 + 0 i "
( 5 - 9i ) - ( 2 + 6i ) "=> 3 - 15 i "
( 5 + 3i ) * ( 5 + 8i ) "=> 1 + 55 i "
( 9 - 7i ) / ( 9 - 3i ) "=> (17/15) - (2/5) i "
( 9.0 - 7.0i ) / ( 9.0 - 3.0i ) "=> 1.133333333333333 - 0.4 i "
( 2 + 3i ) abs "=> 3.60555127546399 "
|
D言語で。複素数は組込みなので楽ちん。2.029で動作確認しました。 実行結果: 7+0i 3+-15i 1+55i 1.13333+-0.4i 3.60555
1 2 3 4 5 6 7 8 9 10 11 | import std.stdio;
import std.math; // for abs
void main()
{
writefln("%s", (3 + 1i) + (4 - 1i));
writefln("%s", (5 - 9i) - (2 + 6i));
writefln("%s", (5 + 3i) * (5 + 8i));
writefln("%s", (9 - 7i) / (9 - 3i));
writefln("%s", abs(2 + 3i));
}
|
1 2 3 4 5 6 7 8 9 10 11 | # open Complex;;
# add { re = 3.0; im = 1.0 } { re = 4.0; im = -1.0 };;
- : Complex.t = {re = 7.; im = 0.}
# sub { re = 5.0; im = -9.0 } { re = 2.0; im = 6.0 };;
- : Complex.t = {re = 3.; im = -15.}
# mul { re = 5.0; im = 3.0 } { re = 5.0; im = 8.0 };;
- : Complex.t = {re = 1.; im = 55.}
# div { re = 9.0; im = -7.0 } { re = 9.0; im = -3.0 };;
- : Complex.t = {re = 1.1333333333333333; im = -0.4}
# norm { re = 2.0; im = 3.0 };;
- : float = 3.60555127546398957
|
1 2 3 4 5 6 7 8 9 10 11 | >> require 'complex'
>> puts Complex(3.0, 1.0) + Complex(4.0, -1.0)
7.0+0.0i
>> puts Complex(5.0, -9.0) - Complex(2.0, 6.0)
3.0-15.0i
>> puts Complex(5.0, 3.0) * Complex(5.0, 8.0)
1.0+55.0i
>> puts Complex(9.0, -7.0) / Complex(9.0, -3.0)
1.13333333333333-0.4i
>> puts Complex(2.0, 3.0).abs
3.60555127546399
|
×整数にメッセージ i を → ○実数にメッセージ i を
F#(fsi)での実行例 dll の読み込みは、オプションでもできます。
1 2 3 4 5 6 7 | > #r "FSharp.PowerPack.dll";;
> open Math.Complex;;
> (complex 3. 1.) + (complex 4. -1.);;
> (complex 5. -9.) - (complex 2. 6.);;
> (complex 5. 3.) * (complex 5. 8.);;
> (complex 9. -7.) / (complex 9. -3.);;
> magnitude (complex 2. 3.) ;;
|
1 2 3 4 5 6 7 8 9 10 11 | >> require 'complex'
>> puts (3.0 + 1.0.im) + (4.0 - 1.0.im)
7.0+0.0i
>> puts (5.0 - 9.0.im) - (2.0 + 6.0.im)
3.0-15.0i
>> puts (5.0 + 3.0.im) * (5.0 + 8.0.im)
1.0+55.0i
>> puts (9.0 - 7.0.im) / (9.0 - 3.0.im)
1.13333333333333-0.4i
>> puts (2.0 + 3.0.im).abs
3.60555127546399
|
結果を整形する場合には、 > printfn "%O" ((complex 3. 1.) + (complex 4. -1.));; とかして下さい。
言語は ViViScript 実行結果: (7, 0) (3, -15) (1, 55) (1.13333, -0.4) 3.60555
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class complex
{
function complex(r, i)
{
this.r = double(r); // 実数部
this.i = double(i); // 虚数部
}
function format() { return "(" + this.r + ", " + this.i + ")"; }
}
function complex_add(lhs, rhs)
{
return new complex(lhs.r + rhs.r, lhs.i + rhs.i);
}
function complex_sub(lhs, rhs)
{
return new complex(lhs.r - rhs.r, lhs.i - rhs.i);
}
function complex_mul(lhs, rhs)
{
return new complex(lhs.r * rhs.r - lhs.i * rhs.i, lhs.r * rhs.i + lhs.i * rhs.r);
}
function complex_div(lhs, rhs)
{
$t = (rhs.r * rhs.r + rhs.i * rhs.i);
return new complex((lhs.r * rhs.r + lhs.i * rhs.i) / $t, (lhs.i * rhs.r - lhs.r * rhs.i) / $t);
}
function complex_abs(c)
{
return Math.sqrt(c.r * c.r + c.i * c.i);
}
cout << complex_add(new complex(3, 1), new complex(4, -1)).format() << "\n";
cout << complex_sub(new complex(5, -9), new complex(2, 6)).format() << "\n";
cout << complex_mul(new complex(5, 3), new complex(5, 8)).format() << "\n";
cout << complex_div(new complex(9, -7), new complex(9, -3)).format() << "\n";
cout << complex_abs(new complex(2, 3)) << "\n";
|
絶対値を求めるのに必要な平方根を求める関数が標準では用意されないので頑張って作ってみたりなど、本質でない部分に労力が... 使えるならEXSLTを使うといいかも。
下記のようなxmlにxsltを適応すると計算できます。:
<complex-list>
<add>
<complex real="3" imag="1" />
<complex real="4" imag="-1" />
</add>
<sub>
<complex real="5" imag="-9" />
<complex real="2" imag="6" />
</sub>
<mul>
<complex real="5" imag="3" />
<complex real="5" imag="8" />
</mul>
<div>
<complex real="9" imag="-7" />
<complex real="9" imag="-3" />
</div>
<abs>
<complex real="2" imag="3" />
</abs>
</complex-list>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:my="uri:ja.doukaku.org:my-functions"
exclude-result-prefixes="my"
>
<xsl:output method="text" />
<xsl:template match="/complex-list" >
<xsl:for-each select="complex|add|sub|mul|div|abs">
<xsl:variable name="complex" as="xs:decimal*">
<xsl:sequence select="my:evaluate-node(.)" />
</xsl:variable>
<xsl:value-of select="my:complex-to-string($complex[1], $complex[2])" />
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:function name="my:complex-to-string" as="xs:string">
<xsl:param name="real" as="xs:decimal" />
<xsl:param name="imag" as="xs:decimal" />
<xsl:variable name="realstr" as="xs:string" select="xs:string($real)" />
<xsl:variable name="imagsign" as="xs:string">
<xsl:choose>
<xsl:when test="$imag gt 0">
<xsl:value-of select="'+'" />
</xsl:when>
<xsl:when test="$imag lt 0">
<xsl:value-of select="'-'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="''" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="imagstr" as="xs:string">
<xsl:choose>
<xsl:when test="fn:abs($imag)=1.0">
<xsl:value-of select="''" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="fn:abs($imag)" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$imag=0">
<xsl:value-of select="$realstr" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="fn:string-join(($realstr, $imagsign, fn:concat($imagstr, 'i')), ' ')" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-node" as="xs:decimal*">
<xsl:param name="node" as="node()" />
<xsl:variable name="node-name" as="xs:string" select="fn:name($node)" />
<xsl:variable name="complex" as="xs:decimal*">
<xsl:for-each select="$node/*">
<xsl:sequence select="my:evaluate-node(.)" />
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="$node-name = 'complex'">
<xsl:sequence select="$node/@real" />
<xsl:choose>
<xsl:when test="fn:exists($node/@imag)">
<xsl:sequence select="$node/@imag" />
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="0" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$node-name = 'add'">
<xsl:sequence select="my:evaluate-add($complex)" />
</xsl:when>
<xsl:when test="$node-name = 'sub'">
<xsl:sequence select="my:evaluate-sub($complex)" />
</xsl:when>
<xsl:when test="$node-name = 'mul'">
<xsl:sequence select="my:evaluate-mul($complex)" />
</xsl:when>
<xsl:when test="$node-name = 'div'">
<xsl:sequence select="my:evaluate-div($complex)" />
</xsl:when>
<xsl:when test="$node-name = 'abs'">
<xsl:sequence select="my:evaluate-abs($complex)" />
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
<xsl:text>*** unknown element name </xsl:text>
<xsl:value-of select="$node-name" />
<xsl:text> ***</xsl:text>
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-add" as="xs:decimal*">
<xsl:param name="values" as="xs:decimal*" />
<xsl:choose>
<xsl:when test="fn:empty($values)">
<xsl:sequence select="(0,0)" />
</xsl:when>
<xsl:when test="fn:count($values)=2">
<xsl:sequence select="$values" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="intermediate" as="xs:decimal*">
<xsl:sequence select="$values[1] + $values[3]" />
<xsl:sequence select="$values[2] + $values[4]" />
<xsl:sequence select="$values[fn:count(.) gt 4]" />
</xsl:variable>
<xsl:sequence select="my:evaluate-add($intermediate)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-sub" as="xs:decimal*">
<xsl:param name="values" as="xs:decimal*" />
<xsl:choose>
<xsl:when test="fn:empty($values)">
<xsl:sequence select="(0,0)" />
</xsl:when>
<xsl:when test="fn:count($values)=2">
<xsl:sequence select="$values" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="intermediate" as="xs:decimal*">
<xsl:sequence select="$values[1] - $values[3]" />
<xsl:sequence select="$values[2] - $values[4]" />
<xsl:sequence select="$values[fn:count(.) gt 4]" />
</xsl:variable>
<xsl:sequence select="my:evaluate-sub($intermediate)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-mul" as="xs:decimal*">
<xsl:param name="values" as="xs:decimal*" />
<xsl:choose>
<xsl:when test="fn:empty($values)">
<xsl:sequence select="(0,0)" />
</xsl:when>
<xsl:when test="fn:count($values)=2">
<xsl:sequence select="$values" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="intermediate" as="xs:decimal*">
<xsl:sequence select="$values[1] * $values[3] - $values[2] * $values[4]" />
<xsl:sequence select="$values[1] * $values[4] + $values[2] * $values[3]" />
<xsl:sequence select="$values[fn:count(.) gt 4]" />
</xsl:variable>
<xsl:sequence select="my:evaluate-mul($intermediate)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-div" as="xs:decimal*">
<xsl:param name="values" as="xs:decimal*" />
<xsl:choose>
<xsl:when test="fn:empty($values)">
<xsl:sequence select="(0,0)" />
</xsl:when>
<xsl:when test="fn:count($values)=2">
<xsl:sequence select="$values" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="intermediate" as="xs:decimal*">
<xsl:variable name="d" as="xs:decimal"
select="$values[3] * $values[3] + $values[4] * $values[4]" />
<xsl:sequence select="($values[1] * $values[3] + $values[2] * $values[4]) div $d" />
<xsl:sequence select="($values[1] * $values[4] - $values[2] * $values[3]) div $d" />
<xsl:sequence select="$values[fn:count(.) gt 4]" />
</xsl:variable>
<xsl:sequence select="my:evaluate-div($intermediate)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:evaluate-abs" as="xs:decimal*">
<xsl:param name="values" as="xs:decimal*" />
<xsl:sequence select="my:sqrt($values[1] * $values[1] + $values[2] * $values[2])" />
<xsl:sequence select="0" />
</xsl:function>
<xsl:function name="my:sqrt" as="xs:decimal">
<xsl:param name="n" as="xs:decimal" />
<xsl:variable name="base" as="xs:integer*">
<xsl:variable name="nstr" as="xs:string" select="xs:string($n)" />
<xsl:for-each select="0 to
($n idiv fn:string-length(if (fn:contains($nstr, '.'))
then (fn:substring-before($nstr, '.'))
else ($nstr)))" >
<xsl:if test=". * . ge $n">
<xsl:sequence select="." />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="my:sqrt-search($n, $base[1], 10)" />
</xsl:function>
<xsl:function name="my:sqrt-search-base" as="xs:integer" >
<xsl:param name="n" as="xs:decimal" />
<xsl:param name="m" as="xs:integer" />
<xsl:choose>
<xsl:when test="$m * $m lt $n">
<xsl:value-of select="my:sqrt-search-base($n, $m + 1)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$m" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="my:sqrt-search">
<xsl:param name="n" as="xs:decimal" />
<xsl:param name="m" as="xs:decimal" />
<xsl:param name="prec" as="xs:integer" />
<xsl:choose>
<xsl:when test="$prec = 0">
<xsl:value-of select="$m" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="my:sqrt-search($n, (($m + ($n div $m)) div 2), $prec - 1)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>
|
122,143,164,187行目の fn:count(.) gt 4 は fn:position() gt 4 の間違いでした。
何という恥ずかしいミス...
つーわけで、自分で-1
例)
var c0 = new Complex(0, 1);
var c1 = new Complex([1, 1]);
var c2 = new Complex({r:3, i:-4});
var c3 = new Complex("5-8i");
alert((new Complex("3+2i")).mul("5-i").mul("-6+2i").div("5-i").div("-6+2i"));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | var Complex = function (arg0, arg1){
arg0 = arg0 || 0;
arg1 = arg1 || 0;
if (typeof arg0 == "number" && typeof arg1 == "number"){
this.r = arg0;
this.i = arg1;
} else {
var tmp = Complex.conv(arg0)
this.r = tmp.r;
this.i = tmp.i;
}
};
// 加減乗除メソッドは破壊的
Complex.prototype = {
toString: function(){return Complex.toString(this);},
valueOf: function(){return Complex.toString(this);},
abs: function(){return Complex.abs(this);},
add: function(cn){
var tmp = Complex.add(this, cn);
this.r = tmp.r;
this.i = tmp.i;
return this;
},
sub: function(cn){
var tmp = Complex.sub(this, cn);
this.r = tmp.r;
this.i = tmp.i;
return this;
},
mul: function(cn){
var tmp = Complex.mul(this, cn);
this.r = tmp.r;
this.i = tmp.i;
return this;
},
div: function(cn){
var tmp = Complex.div(this, cn);
this.r = tmp.r;
this.i = tmp.i;
return this;
}
};
// 以下はインスタンスのメソッドではない
// 引数をインスタンスもどき(メソッドなしでプロパティr, iのみのオブジェクト)に変換する関数
Complex.conv = function(arg){
if (typeof arg == "object") {
return {r: Number(arg.r || arg[0] || 0), i: Number(arg.i || arg[1] || 0)};
} else if (typeof arg == "string") {
var srcNum = "([+\\-]?(?:[0-9]+\\.?[0-9]*|0?\\.[0-9]+)(?:e[+\\-]?[0-9]+)?)";
var reCNum = new RegExp("^(?:" + srcNum + "(?!i))?(?:" + srcNum + "i)?$", "i");
reCNum.exec(arg.replace(/\s/g, "").replace(/(^|\+|-)i/i, "$11i"));
return {r: Number(RegExp.$1), i: Number(RegExp.$2)};
}
return {r: Number(arg), i: 0};
};
// インスタンス相当を引数に取る関数
Complex.toString = function(cn){
cn = Complex.conv(cn);
return cn.r.toString() + (cn.i >= 0 ? "+" : "") + cn.i.toString() + "i";
};
Complex.abs = function(cn){
cn = Complex.conv(cn);
return Math.sqrt(cn.r * cn.r + cn.i * cn.i);
};
// 加減乗除関数は新しいインスタンスを返す
Complex.add = function(cn0, cn1){
cn0 = Complex.conv(cn0);
cn1 = Complex.conv(cn1);
return new Complex(cn0.r + cn1.r, cn0.i + cn1.i);
};
Complex.sub = function(cn0, cn1){
cn0 = Complex.conv(cn0);
cn1 = Complex.conv(cn1);
return new Complex(cn0.r - cn1.r, cn0.i - cn1.i);
};
Complex.mul = function(cn0, cn1){
cn0 = Complex.conv(cn0);
cn1 = Complex.conv(cn1);
return new Complex(cn0.r * cn1.r - cn0.i * cn1.i,
cn0.i * cn1.r + cn0.r * cn1.i);
};
Complex.div = function(cn0, cn1){
cn0 = Complex.conv(cn0);
cn1 = Complex.conv(cn1);
var absSq = cn1.r * cn1.r + cn1.i * cn1.i;
return new Complex((cn0.r * cn1.r + cn0.i * cn1.i) / absSq,
(cn0.i * cn1.r - cn0.r * cn1.i) / absSq);
};
// 定義部はここまで
/* お題の計算。結果は以下
7+0i
3-15i
1+55i
1.1333333333333333-0.4i
3.605551275463989
*/
alert(
Complex.add(new Complex(3, 1), new Complex(4, -1))
+ "\n" + Complex.sub(new Complex(5, -9), new Complex(2, 6))
+ "\n" + Complex.mul(new Complex(5, 3), new Complex(5, 8))
+ "\n" + Complex.div(new Complex(9, -7), new Complex(9, -3))
+ "\n" + Complex.abs(new Complex(2, 3))
);
// インスタンスを作る。引数は数値2つ、
// もしくは数値要素を2つ持つ(連想)配列か、複素数と解釈できる文字列
var c0 = new Complex(0, 1);
var c1 = new Complex([1, 1]);
var c2 = new Complex({r:3, i:-4});
var c3 = new Complex("5-8i");
// 絶対値を出してみる。上3行と下3行の結果は同じ。
alert(
"|" + c0 + "| = " + Complex.abs(c0)
+ "\n" + "|" + c1 + "| = " + Complex.abs(c1)
+ "\n" + "|" + c2 + "| = " + Complex.abs(c2)
+ "\n" + "|" + c0 + "| = " + c0.abs()
+ "\n" + "|" + c1 + "| = " + c1.abs()
+ "\n" + "|" + c2 + "| = " + c2.abs()
);
// 計算1。引数なら文字列のままでも可。
// 下3行の計算は破壊的(c0の値が計算結果に変わる)
alert(
"(" + c0 + ") + (" + c1 + ") = " + Complex.add(c0, c1)
+ "\n(" + c0 + ") - (" + c2 + ") = " + Complex.sub(c0, c2)
+ "\n(" + c0 + ") / (" + "-i" + ") = " + Complex.div(c0, "-i")
+ "\n(" + c0 + ") + (" + c1 + ") = " + c0.add(c1)
+ "\n(" + c0 + ") - (" + c2 + ") = " + c0.sub(c2)
+ "\n(" + c0 + ") / (" + "-i" + ") = " + c0.div("-i")
);
// 計算2。iの2乗。加減乗除の組み合わせ2つ。複素数を0で割ると0/0
alert(
"i * i = " + Complex.mul("i", "i")
+ "\n(3+2i) * (5-i) * (-6+2i) / (5-i) / (-6+2i) = "
+ (new Complex("3+2i")).mul("5-i").mul("-6+2i").div("5-i").div("-6+2i")
+ "\n( (3+2i) + (4-i) ) * 2i * -.5i - (4-i) = "
+ Complex.add("3+2i", "4-i").mul("2i").mul("-.5i").sub("4-i")
+ "\n(1+2i) / 0 = " + Complex.div("1+2i", "0")
);
// 引数いろいろ。falsyな値や空配列は0+0iに
var testcases = [
"-3-8i", "5", [0, 4], [2, -8],
"-2+i", "-2-i", {r:-2.5, i:3e-2}, "-2E8 + I",
"0", "i", Infinity, NaN, "", {}, null, undefined
];
for (var i = 0, rslt = ""; i < testcases.length; i++){
rslt += (typeof testcases[i]) + ": " + testcases[i]
+ "\n\t\t" + (new Complex(testcases[i])) + "\n";
}
alert(rslt);
|
SQL Server 2008 で確認しました。
入力が微妙ですが、問題ID, 種類(左辺:1、演算子:2、右辺:3), 実部, 虚部, 演算子(加算:1、減算:2、乗算:3、除算:4、絶対値:5)を与えます。
すると、Resultsとして問題IDの答えの実部と虚部が取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | WITH
Input(id, kind, real_part, img_part, op) AS (
-- (3 + i) + (4 - i)
SELECT 1, 1, 3, 1, CAST(NULL AS int)
UNION ALL
SELECT 1, 2, NULL, NULL, 1
UNION ALL
SELECT 1, 3, 4, -1, NULL
UNION ALL
-- (5 - 9i) - (2 + 6i)
SELECT 2, 1, 5, -9, NULL
UNION ALL
SELECT 2, 2, NULL, NULL, 2
UNION ALL
SELECT 2, 3, 2, 6, NULL
UNION ALL
-- (5 + 3i) * (5 + 8i)
SELECT 3, 1, 5, 3, NULL
UNION ALL
SELECT 3, 2, NULL, NULL, 3
UNION ALL
SELECT 3, 3, 5, 8, NULL
UNION ALL
-- (9 - 7i) / (9 - 3i)
SELECT 4, 1, 9, -7, NULL
UNION ALL
SELECT 4, 2, NULL, NULL, 4
UNION ALL
SELECT 4, 3, 9, -3, NULL
UNION ALL
-- |2 + 3i|
SELECT 5, 1, 2, 3, NULL
UNION ALL
SELECT 5, 2, NULL, NULL, 5
)
, Interval(id, l_real, l_img, op, r_real, r_img) AS (
SELECT
id
, SUM(CASE kind WHEN 1 THEN real_part ELSE 0 END)
, SUM(CASE kind WHEN 1 THEN img_part ELSE 0 END)
, SUM(CASE kind WHEN 2 THEN op ELSE 0 END)
, SUM(CASE kind WHEN 3 THEN real_part ELSE 0 END)
, SUM(CASE kind WHEN 3 THEN img_part ELSE 0 END)
FROM
Input
GROUP BY
id
)
, Results(id, real_part, img_part) AS (
SELECT
id
, CASE op
WHEN 1 THEN l_real + r_real
WHEN 2 THEN l_real - r_real
WHEN 3 THEN (l_real * r_real) - (l_img * r_img)
WHEN 4 THEN ((l_real * r_real) + (l_img * r_img)) /
(SQUARE(r_real) + SQUARE(r_img))
WHEN 5 THEN SQRT(SQUARE(l_real) + SQUARE(l_img))
END
, CASE op
WHEN 1 THEN l_img + r_img
WHEN 2 THEN l_img - r_img
WHEN 3 THEN (l_img * r_real) + (l_real * r_img)
WHEN 4 THEN ((l_img * r_real) - (l_real * r_img)) /
(SQUARE(r_real) + SQUARE(r_img))
WHEN 5 THEN 0
END
FROM
Interval
)
SELECT * FROM Results
|
演算子オーバーロードを使ってスクラッチで実装。 Perlの真骨頂。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #!/usr/bin/perl
use strict;
use warnings;
package ComplexNumber;
use overload
'""' => \&toString,
'+' => \&add,
'-' => \&sub,
'*' => \&mul,
'/' => \&div,
'0+' => \&val,
;
sub new{
my ($class, $real, $imagin) = @_;
return unless defined($real);
if($real =~ /^[-+]?\d+(\.\d+)?$/ and
(!defined($imagin) or $imagin =~ /^[-+]?\d*(\d\.\d+)?i?$/))
{#$real, $imagin両方に数値が渡ってきた時。$imaginが未定義/末尾にiは許容
$real =~ s/\+//;
$imagin =~ s/[i+]//g if $imagin;
$imagin = 0 unless $imagin;
return bless {a=>$real, b=>$imagin}, $class;
}
return if $imagin;
if($real =~ /^[-+]?\d+(\.\d+)?i$/){#第1引数 に 文字列'5i'とかが渡された時
$real =~ s/[i+]//g;
return bless {a=>0, b=>$real}, $class;
}
$real =~ s/\s//g;
if(my ($real2, $imagin2) = $real =~ /^([-+]?\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?)i$/){
#第1引数 に 文字列(ex. '5+4.8i')が渡された時
$real2 =~ s/\+//;
$imagin2 =~ s/\+//;
return bless {a=>$real2, b=>$imagin2}, $class;
}
return;
}
sub toString{
my $self = shift;
return $self->{'a'} if $self->{'b'} == 0;
return (abs($self->{'b'}) != 1 ? $self->{'b'} : '-') . 'i'
if $self->{'a'} == 0;
return $self->{'a'} .
($self->{'b'} > 0 ? '+' : '') .
(abs($self->{'b'}) != 1 ? $self->{'b'} : '-') .'i';
}
sub add{
my ($self, $src) = @_;
$src = ComplexNumber->new($src) unless eval{$src->isa('ComplexNumber')};
return $src ?
ComplexNumber->new($self->{'a'}+$src->{'a'}, $self->{'b'}+$src->{'b'}) : ();
}
sub sub{
my ($dest, $src, $rev) = @_;
$src = ComplexNumber->new($src) unless eval{$src->isa('ComplexNumber')};
return unless $src;
($dest, $src) = ($src, $dest) if $rev;
return ComplexNumber->new($dest->{'a'}-$src->{'a'}, $dest->{'b'}-$src->{'b'});
}
sub mul{
my ($dest, $src) = @_;
$src = ComplexNumber->new($src) unless eval{$src->isa('ComplexNumber')};
return $src ?
ComplexNumber->new(
$dest->{'a'}*$src->{'a'} - $dest->{'b'}*$src->{'b'},
$dest->{'a'}*$src->{'b'} + $dest->{'b'}*$src->{'a'}
) : ();
}
sub div{
my ($dest, $src, $rev) = @_;
$src = ComplexNumber->new($src) unless eval{$src->isa('ComplexNumber')};
return unless $src;
($dest, $src) = ($src, $dest) if $rev;
return ComplexNumber->new(
($dest->{'a'}*$src->{'a'}+$dest->{'b'}*$src->{'b'})/($src->{'a'}**2 + $src->{'b'}**2),
($dest->{'b'}*$src->{'a'}-$dest->{'a'}*$src->{'b'})/($src->{'a'}**2 + $src->{'b'}**2),
);
}
sub abs{
my $self = shift;
return sqrt($self->{'a'}**2 + $self->{'b'}**2)
}
sub val{
my $self = shift;
return $self->{'a'};
}
package main;
my $comp1 = ComplexNumber->new(8, 6.3);
my $comp2 = ComplexNumber->new('4 - 8.5i');
print $comp1 + $comp2 ."\n";
print $comp1 - $comp2 ."\n";
print $comp1 * $comp2 ."\n";
print $comp1 / $comp2 ."\n\n";
print $comp1 + 8 ."\n";
print $comp1 - 8 ."\n";
print 8 - $comp1 ."\n";
print $comp1 * 8 ."\n";
print $comp1 / 8 ."\n";
print 8 / $comp1 ."\n";
print $comp1->abs;
|
#8851をパラメタ付に改造してみました。 Complex[Int],Complex[Double]
もう、ぐだぐだ。
制限事項 整数と実数の混合ができない orz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | // 複素数(お題:http://ja.doukaku.org/247/)
// http://ja.doukaku.org/comment/----/
// snaさん作を改変( : http://ja.doukaku.org/comment/8851/)
// 参考 : http://en.literateprograms.org/Complex_numbers_(Scala)
trait Arithmetic[T<:AnyVal]{
def unary_+ : T
def unary_- : T
def + (that:T):T
def - (that:T):T
def * (that:T):T
def / (that:T):T
def abs : T
//
def lt0 : Boolean // > 0
def gt0 : Boolean // < 0
def eq0 : Boolean // == 0
//
def eqp1 : Boolean // == 1
def eqm1 : Boolean // == -1
//
}
case class Complex[ T<%Arithmetic[T] ](real:T, imag:T) {
// +(a + bi) = (a + bi)
def unary_+ = this
// -(a + bi) = (-a - bi)
def unary_- = Complex[T](-real, -imag)
// (a + bi) + (c + di) = (a + c) + (b + d)i
def + (that: Complex[T]) = Complex(this.real + that.real, this.imag + that.imag)
// (a + bi) - (c + di) = (a - c) + (b - d)i
def - (that: Complex[T]) = Complex(this.real - that.real, this.imag - that.imag)
// (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
def * (that: Complex[T]) = {
val Complex(a, b) = this
val Complex(c, d) = that
Complex(a*c - b*d, b*c + a*d)
}
// (a + bi) / (c + di) = (ac + bd) / (c^2 + d^2) + (bc - ad) / (c^2 + d^2)
def / (that: Complex[T]) = {
val Complex(a, b) = this
val Complex(c, d) = that
val deno = c*c + d*d
Complex((a*c + b*d) / deno, (b*c - a*d) / deno)
}
// Conjugate
def conjugate() : Complex[T] = Complex(real,-imag)
override def toString = this match {
case Complex(re, im) if im.eq0 => re.toString
case Complex(re, im) if re.eq0 && im.eqp1 => "i"
case Complex(re, im) if re.eq0 && im.eqm1 => "-i"
case Complex(re, im) if re.eq0 => im.toString + "i"
case Complex(re, im) if im.eqp1 => re.toString + " + i"
case Complex(re, im) if im.eqm1 => re.toString + " - i"
case Complex(re, im) if im.gt0 => re.toString + " + " + im.toString + "i"
case Complex(re, im) if im.lt0 => re.toString + " - " + im.abs.toString + "i"
}
}
object test{
implicit def int2Arithmeic(n:Int) : Arithmetic[Int] =
new Arithmetic[Int]{
def unary_+ : Int = n.unary_+
def unary_- : Int = n.unary_-
def + (that:Int):Int = n+that
def - (that:Int):Int = n-that
def * (that:Int):Int = n*that
def / (that:Int):Int = n/that
def abs = Math.abs(n)
//
def lt0 = n<0
def gt0 = n>0
def eq0 = n==0
//
def eqp1 = n==1
def eqm1 = n== -1 }
implicit def double2Arithmeic(n:Double) : Arithmetic[Double] =
new Arithmetic[Double]{
def unary_+ : Double = n.unary_+
def unary_- : Double = n.unary_-
def + (that:Double):Double = n+that
def - (that:Double):Double = n-that
def * (that:Double):Double = n*that
def / (that:Double):Double = n/that
def abs = Math.abs(n)
//
def lt0 = n<0
def gt0 = n>0
def eq0 = n==0
//
def eqp1 = n==1
def eqm1 = n== -1 }
implicit def int2Complex (n:Int ):Complex[Int ] = Complex(n,0)
implicit def double2Complex(n:Double):Complex[Double] = Complex(n,0)
implicit def icomp2dcomp (z:Complex[Int]):Complex[Double] = Complex(z.real,z.imag)
implicit def dcomp2richer (z:Complex[Double]) = new Proxy{
val self=z
def abs = self match {
case Complex(re, im) => Math.sqrt(re*re + im*im)
}
}
implicit def icomp2richer (z:Complex[int]) = new Proxy{
val self=z
def abs = self match {
case Complex(re, im) => Math.sqrt(re*re + im*im)
}
}
def main( args:Array[String] ) : Unit = {
{
val i = Complex(0,1)
println( (3 + i ) + (4 - i ) )
println( (5 - 9*i) - (2 + 6*i) )
println( (5 + 3*i) * (5 + 8*i) )
println( (9 - 7*i) / (9 - 3*i) )
println( (2 + 3*i).abs )
}
{
val i = Complex(0.,1.)
println( (3. + i ) + (4. - i ) )
println( (5. - 9.*i) - (2. + 6.*i) )
println( (5. + 3.*i) * (5. + 8.*i) )
println( (9. - 7.*i) / (9. - 3.*i) )
println( (2. + 3.*i).abs )
}
}
}
|
Groovyで。結果は以下の通り。 .iあたりが気に入っている。
7.0+0.0i 3.0-15.0i 1.0+55.0i 1.1333333333333333-0.4i 3.605551275463989
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Complex {
double re
double im
Complex(re, im) { this.re = re; this.im = im }
Complex plus(c) { new Complex(re+c.re, im+c.im) }
Complex minus(c) { new Complex(re-c.re, im-c.im) }
Complex multiply(c) { new Complex(re*c.re - im*c.im, re*c.im + im*c.re) }
Complex div(c) {
def denom = (c.re ** 2) + (c.im ** 2)
new Complex((re*c.re+im*c.im)/denom, (im*c.re-re*c.im)/denom)
}
double abs(){ Math.sqrt(re ** 2 + im ** 2) }
static final i = new Complex(0, 1)
String toString() { re+(im>=0?'+':'')+im+'i' }
}
['plus','minus','multiply','div'].each {
Number.metaClass."$it" = { Complex c -> new Complex(delegate, 0)."$it"(c) }
}
Number.metaClass.getI = {new Complex(0, delegate)}
def i = Complex.i
println ((3 + i) + (4 - i))
println ((5 - 9.i) - (2 + 6.i))
println ((5 + 3.i) * (5 + 8.i))
println ((9 - 7.i) / (9 - 3.i))
println ((2 - 3.i).abs())
|





syat
#8845()
Rating4/6=0.67
1. 加算 ( 3 + i ) + ( 4 - i )
2. 減算 ( 5 - 9i ) - ( 2 + 6i )
3. 乗算 ( 5 + 3i ) * ( 5 + 8i )
4. 除算 ( 9 - 7i ) / ( 9 - 3i )
5. 絶対値 | 2 + 3i |
複素数計算を行う関数やクラスを定義して答えを求めること。
ライブラリがある場合はそれを利用してかまいません。
see: Wikipedia:複素数
[ reply ]