類別 Complex
Complex 物件包含一對值,這些值在建立物件時提供,可以是直角坐標或極坐標。
直角坐標¶ ↑
複數的直角坐標稱為實部和虛部;請參閱 複數定義。
您可以使用直角坐標建立 Complex 物件,方法如下:
-
複數文字。
-
方法
Complex.rect
。 -
方法
Kernel#Complex
,使用數字引數或特定字串引數。 -
方法
String#to_c
,針對特定字串。
請注意,每個儲存的區塊可能是 Complex
、Float
、Integer
或 Rational
類別的執行個體之一;它們可以透過下列方式擷取:
-
分別使用
Complex#real
和Complex#imaginary
方法。 -
一起使用
Complex#rect
方法。
可以透過下列方式擷取對應的(計算的)極坐標值:
-
分別使用
Complex#abs
和Complex#arg
方法。 -
一起使用
Complex#polar
方法。
極坐標¶ ↑
複數的極坐標稱為絕對值和幅角;請參閱 複數極平面。
您可以使用
-
方法
Complex.polar
從極座標建立一個複數物件。 -
方法
Kernel#Complex
,使用特定的字串引數。 -
方法
String#to_c
,針對特定字串。
請注意,每個儲存的區塊可能是 Complex
、Float
、Integer
或 Rational
類別的執行個體之一;它們可以透過下列方式擷取:
-
分別使用
Complex#abs
和Complex#arg
方法。 -
一起使用
Complex#polar
方法。
對應的(計算出的)直角座標值可以透過
-
方法
Complex#real
和Complex#imag
分別取得。 -
一起使用
Complex#rect
方法。
常數
- I
等於
Complex(0, 1)
Complex::I # => (0+1i)
公開類別方法
請參閱 as_json
。
# File ext/json/lib/json/add/complex.rb, line 9 def self.json_create(object) Complex(object['r'], object['i']) end
傳回一個新的複數物件,由引數組成,每個引數都必須是 Numeric
的執行個體,或其子類別的執行個體:Complex、Float
、Integer
、Rational
。引數 arg
以弧度為單位;請參閱 極座標
Complex.polar(3) # => (3+0i) Complex.polar(3, 2.0) # => (-1.2484405096414273+2.727892280477045i) Complex.polar(-3, -2.0) # => (1.2484405096414273+2.727892280477045i)
static VALUE nucomp_s_polar(int argc, VALUE *argv, VALUE klass) { VALUE abs, arg; argc = rb_scan_args(argc, argv, "11", &abs, &arg); abs = nucomp_real_check(abs); if (argc == 2) { arg = nucomp_real_check(arg); } else { arg = ZERO; } return f_complex_polar_real(klass, abs, arg); }
傳回一個新的複數物件,由引數組成,每個引數都必須是 Numeric
的執行個體,或其子類別的執行個體:Complex、Float
、Integer
、Rational
;請參閱 直角座標
Complex.rect(3) # => (3+0i) Complex.rect(3, Math::PI) # => (3+3.141592653589793i) Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)
Complex.rectangular 是 Complex.rect 的別名。
static VALUE nucomp_s_new(int argc, VALUE *argv, VALUE klass) { VALUE real, imag; switch (rb_scan_args(argc, argv, "11", &real, &imag)) { case 1: real = nucomp_real_check(real); imag = ZERO; break; default: real = nucomp_real_check(real); imag = nucomp_real_check(imag); break; } return nucomp_s_new_internal(klass, real, imag); }
傳回一個新的複數物件,由引數組成,每個引數都必須是 Numeric
的執行個體,或其子類別的執行個體:Complex、Float
、Integer
、Rational
;請參閱 直角座標
Complex.rect(3) # => (3+0i) Complex.rect(3, Math::PI) # => (3+3.141592653589793i) Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)
Complex.rectangular 是 Complex.rect 的別名。
static VALUE nucomp_s_new(int argc, VALUE *argv, VALUE klass) { VALUE real, imag; switch (rb_scan_args(argc, argv, "11", &real, &imag)) { case 1: real = nucomp_real_check(real); imag = ZERO; break; default: real = nucomp_real_check(real); imag = nucomp_real_check(imag); break; } return nucomp_s_new_internal(klass, real, imag); }
公開執行個體方法
傳回 self
和 numeric
的乘積
Complex(2, 3) * Complex(2, 3) # => (-5+12i) Complex(900) * Complex(1) # => (900+0i) Complex(-2, 9) * Complex(-9, 2) # => (0-85i) Complex(9, 8) * 4 # => (36+32i) Complex(20, 9) * 9.8 # => (196.0+88.2i)
VALUE rb_complex_mul(VALUE self, VALUE other) { if (RB_TYPE_P(other, T_COMPLEX)) { VALUE real, imag; get_dat2(self, other); comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag); return f_complex_new2(CLASS_OF(self), real, imag); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_mul(dat->real, other), f_mul(dat->imag, other)); } return rb_num_coerce_bin(self, other, '*'); }
傳回 self
乘方 numeric
Complex('i') ** 2 # => (-1+0i) Complex(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)
VALUE rb_complex_pow(VALUE self, VALUE other) { if (k_numeric_p(other) && k_exact_zero_p(other)) return f_complex_new_bang1(CLASS_OF(self), ONE); if (RB_TYPE_P(other, T_RATIONAL) && RRATIONAL(other)->den == LONG2FIX(1)) other = RRATIONAL(other)->num; /* c14n */ if (RB_TYPE_P(other, T_COMPLEX)) { get_dat1(other); if (k_exact_zero_p(dat->imag)) other = dat->real; /* c14n */ } if (other == ONE) { get_dat1(self); return nucomp_s_new_internal(CLASS_OF(self), dat->real, dat->imag); } VALUE result = complex_pow_for_special_angle(self, other); if (result != Qundef) return result; if (RB_TYPE_P(other, T_COMPLEX)) { VALUE r, theta, nr, ntheta; get_dat1(other); r = f_abs(self); theta = f_arg(self); nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)), f_mul(dat->imag, theta))); ntheta = f_add(f_mul(theta, dat->real), f_mul(dat->imag, m_log_bang(r))); return f_complex_polar(CLASS_OF(self), nr, ntheta); } if (FIXNUM_P(other)) { long n = FIX2LONG(other); if (n == 0) { return nucomp_s_new_internal(CLASS_OF(self), ONE, ZERO); } if (n < 0) { self = f_reciprocal(self); other = rb_int_uminus(other); n = -n; } { get_dat1(self); VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi; if (f_zero_p(xi)) { zr = rb_num_pow(zr, other); } else if (f_zero_p(xr)) { zi = rb_num_pow(zi, other); if (n & 2) zi = f_negate(zi); if (!(n & 1)) { VALUE tmp = zr; zr = zi; zi = tmp; } } else { while (--n) { long q, r; for (; q = n / 2, r = n % 2, r == 0; n = q) { VALUE tmp = f_sub(f_mul(xr, xr), f_mul(xi, xi)); xi = f_mul(f_mul(TWO, xr), xi); xr = tmp; } comp_mul(zr, zi, xr, xi, &zr, &zi); } } return nucomp_s_new_internal(CLASS_OF(self), zr, zi); } } if (k_numeric_p(other) && f_real_p(other)) { VALUE r, theta; if (RB_BIGNUM_TYPE_P(other)) rb_warn("in a**b, b may be too big"); r = f_abs(self); theta = f_arg(self); return f_complex_polar(CLASS_OF(self), f_expt(r, other), f_mul(theta, other)); } return rb_num_coerce_bin(self, other, id_expt); }
傳回 self
和 numeric
的總和
Complex(2, 3) + Complex(2, 3) # => (4+6i) Complex(900) + Complex(1) # => (901+0i) Complex(-2, 9) + Complex(-9, 2) # => (-11+11i) Complex(9, 8) + 4 # => (13+8i) Complex(20, 9) + 9.8 # => (29.8+9i)
VALUE rb_complex_plus(VALUE self, VALUE other) { if (RB_TYPE_P(other, T_COMPLEX)) { VALUE real, imag; get_dat2(self, other); real = f_add(adat->real, bdat->real); imag = f_add(adat->imag, bdat->imag); return f_complex_new2(CLASS_OF(self), real, imag); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_add(dat->real, other), dat->imag); } return rb_num_coerce_bin(self, other, '+'); }
傳回 self
和 numeric
的差
Complex(2, 3) - Complex(2, 3) # => (0+0i) Complex(900) - Complex(1) # => (899+0i) Complex(-2, 9) - Complex(-9, 2) # => (7+7i) Complex(9, 8) - 4 # => (5+8i) Complex(20, 9) - 9.8 # => (10.2+9i)
VALUE rb_complex_minus(VALUE self, VALUE other) { if (RB_TYPE_P(other, T_COMPLEX)) { VALUE real, imag; get_dat2(self, other); real = f_sub(adat->real, bdat->real); imag = f_sub(adat->imag, bdat->imag); return f_complex_new2(CLASS_OF(self), real, imag); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_sub(dat->real, other), dat->imag); } return rb_num_coerce_bin(self, other, '-'); }
傳回 self
的否定,也就是其每個部分的否定
-Complex(1, 2) # => (-1-2i) -Complex(-1, -2) # => (1+2i)
VALUE rb_complex_uminus(VALUE self) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_negate(dat->real), f_negate(dat->imag)); }
傳回 self
和 numeric
的商
Complex(2, 3) / Complex(2, 3) # => ((1/1)+(0/1)*i) Complex(900) / Complex(1) # => ((900/1)+(0/1)*i) Complex(-2, 9) / Complex(-9, 2) # => ((36/85)-(77/85)*i) Complex(9, 8) / 4 # => ((9/4)+(2/1)*i) Complex(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i)
VALUE rb_complex_div(VALUE self, VALUE other) { return f_divide(self, other, f_quo, id_quo); }
傳回
-
self.real <=> object.real
,如果下列兩者皆為真-
self.imag == 0
. -
object.imag == 0
。# 如果 object 是數字而非複數,則總是為真。
-
-
否則為
nil
。
範例
Complex(2) <=> 3 # => -1 Complex(2) <=> 2 # => 0 Complex(2) <=> 1 # => 1 Complex(2, 1) <=> 1 # => nil # self.imag not zero. Complex(1) <=> Complex(1, 1) # => nil # object.imag not zero. Complex(1) <=> 'Foo' # => nil # object.imag not defined.
static VALUE nucomp_cmp(VALUE self, VALUE other) { if (!k_numeric_p(other)) { return rb_num_coerce_cmp(self, other, idCmp); } if (!nucomp_real_p(self)) { return Qnil; } if (RB_TYPE_P(other, T_COMPLEX)) { if (nucomp_real_p(other)) { get_dat2(self, other); return rb_funcall(adat->real, idCmp, 1, bdat->real); } } else { get_dat1(self); if (f_real_p(other)) { return rb_funcall(dat->real, idCmp, 1, other); } else { return rb_num_coerce_cmp(dat->real, other, idCmp); } } return Qnil; }
如果 self.real == object.real
且 self.imag == object.imag
,則傳回 true
Complex(2, 3) == Complex(2.0, 3.0) # => true
static VALUE nucomp_eqeq_p(VALUE self, VALUE other) { if (RB_TYPE_P(other, T_COMPLEX)) { get_dat2(self, other); return RBOOL(f_eqeq_p(adat->real, bdat->real) && f_eqeq_p(adat->imag, bdat->imag)); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag)); } return RBOOL(f_eqeq_p(other, self)); }
傳回 self
的絕對值 (大小);請參閱 極座標
Complex.polar(-1, 0).abs # => 1.0
如果 self
是使用 直角座標 建立的,則傳回值會經過計算,且可能不精確
Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2.
VALUE rb_complex_abs(VALUE self) { get_dat1(self); if (f_zero_p(dat->real)) { VALUE a = f_abs(dat->imag); if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag)) a = f_to_f(a); return a; } if (f_zero_p(dat->imag)) { VALUE a = f_abs(dat->real); if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag)) a = f_to_f(a); return a; } return rb_math_hypot(dat->real, dat->imag); }
方法 Complex#as_json
和 Complex.json_create
可用於序列化和反序列化 Complex 物件;請參閱 Marshal
。
方法 Complex#as_json
會序列化 self
,傳回一個代表 self
的 2 元素雜湊
require 'json/add/complex' x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0} y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
方法 JSON.create
會將此類雜湊反序列化,傳回一個複數物件
Complex.json_create(x) # => (2+0i) Complex.json_create(y) # => (2.0+4i)
# File ext/json/lib/json/add/complex.rb, line 29 def as_json(*) { JSON.create_id => self.class.name, 'r' => real, 'i' => imag, } end
傳回 self
的共軛,Complex.rect(self.imag, self.real)
Complex.rect(1, 2).conj # => (1-2i)
傳回 self
的分母,也就是 self.real.denominator
和 self.imag.denominator
的最小公倍數
Complex.rect(Rational(1, 2), Rational(2, 3)).denominator # => 6
請注意,非有理數的 n.denominator
為 1
。
static VALUE nucomp_denominator(VALUE self) { get_dat1(self); return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag)); }
傳回 Complex(self.real/numeric, self.imag/numeric)
Complex(11, 22).fdiv(3) # => (3.6666666666666665+7.333333333333333i)
static VALUE nucomp_fdiv(VALUE self, VALUE other) { return f_divide(self, other, f_fdiv, id_fdiv); }
如果 self.real.finite?
和 self.imag.finite?
皆為 true,則傳回 true
,否則傳回 false
Complex(1, 1).finite? # => true Complex(Float::INFINITY, 0).finite? # => false
相關:Numeric#finite?
、Float#finite?
。
static VALUE rb_complex_finite_p(VALUE self) { get_dat1(self); return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag)); }
傳回 self
的整數雜湊值。
由相同值建立的兩個複數物件會擁有相同的雜湊值(並會使用 eql?
進行比較)
Complex(1, 2).hash == Complex(1, 2).hash # => true
static VALUE nucomp_hash(VALUE self) { return ST2FIX(rb_complex_hash(self)); }
傳回 self
的虛值
Complex(7).imaginary #=> 0 Complex(9, -4).imaginary #=> -4
如果 self
是使用 極座標 建立的,傳回的值會經過運算,且可能不精確
Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2.
如果 self.real.infinite?
或 self.imag.infinite?
為 true,則傳回 1
,否則傳回 nil
Complex(Float::INFINITY, 0).infinite? # => 1 Complex(1, 1).infinite? # => nil
相關:Numeric#infinite?
、Float#infinite?
。
static VALUE rb_complex_infinite_p(VALUE self) { get_dat1(self); if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) { return Qnil; } return ONE; }
傳回 self
的字串表示法
Complex(2).inspect # => "(2+0i)" Complex('-8/6').inspect # => "((-4/3)+0i)" Complex('1/2i').inspect # => "(0+(1/2)*i)" Complex(0, Float::INFINITY).inspect # => "(0+Infinity*i)" Complex(Float::NAN, Float::NAN).inspect # => "(NaN+NaN*i)"
static VALUE nucomp_inspect(VALUE self) { VALUE s; s = rb_usascii_str_new2("("); rb_str_concat(s, f_format(self, rb_inspect)); rb_str_cat2(s, ")"); return s; }
傳回從 `self` 的實部和虛部的分子建立的複數物件,在將每個部分轉換成這兩者的最小公分母之後
c = Complex(Rational(2, 3), Rational(3, 4)) # => ((2/3)+(3/4)*i) c.numerator # => (8+9i)
在此範例中,這兩部分的最小公分母為 12;兩個轉換後的部份可以視為 Rational(8, 12) 和 Rational(9, 12),其分子分別為 8 和 9;因此 `c.numerator` 傳回的值為 `Complex(8, 9)`。
static VALUE nucomp_numerator(VALUE self) { VALUE cd; get_dat1(self); cd = nucomp_denominator(self); return f_complex_new2(CLASS_OF(self), f_mul(f_numerator(dat->real), f_div(cd, f_denominator(dat->real))), f_mul(f_numerator(dat->imag), f_div(cd, f_denominator(dat->imag)))); }
傳回 self
和 numeric
的商
Complex(2, 3) / Complex(2, 3) # => ((1/1)+(0/1)*i) Complex(900) / Complex(1) # => ((900/1)+(0/1)*i) Complex(-2, 9) / Complex(-9, 2) # => ((36/85)-(77/85)*i) Complex(9, 8) / 4 # => ((9/4)+(2/1)*i) Complex(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i)
VALUE rb_complex_div(VALUE self, VALUE other) { return f_divide(self, other, f_quo, id_quo); }
傳回一個Rational
物件,其值與 `self.real` 的值完全或近似相等。
如果沒有給定引數 `epsilon`,傳回一個 Rational 物件,其值與 `self.real.rationalize` 的值完全相等
Complex(1, 0).rationalize # => (1/1) Complex(1, Rational(0, 1)).rationalize # => (1/1) Complex(3.14159, 0).rationalize # => (314159/100000)
如果給定引數 `epsilon`,傳回一個 Rational 物件,其值與 `self.real` 的值完全或近似相等,達到指定的精確度
Complex(3.14159, 0).rationalize(0.1) # => (16/5) Complex(3.14159, 0).rationalize(0.01) # => (22/7) Complex(3.14159, 0).rationalize(0.001) # => (201/64) Complex(3.14159, 0).rationalize(0.0001) # => (333/106) Complex(3.14159, 0).rationalize(0.00001) # => (355/113) Complex(3.14159, 0).rationalize(0.000001) # => (7433/2366) Complex(3.14159, 0).rationalize(0.0000001) # => (9208/2931) Complex(3.14159, 0).rationalize(0.00000001) # => (47460/15107) Complex(3.14159, 0).rationalize(0.000000001) # => (76149/24239) Complex(3.14159, 0).rationalize(0.0000000001) # => (314159/100000) Complex(3.14159, 0).rationalize(0.0) # => (3537115888337719/1125899906842624)
相關:Complex#to_r
。
static VALUE nucomp_rationalize(int argc, VALUE *argv, VALUE self) { get_dat1(self); rb_check_arity(argc, 0, 1); if (!k_exact_zero_p(dat->imag)) { rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", self); } return rb_funcallv(dat->real, id_rationalize, argc, argv); }
傳回 `self` 的實數值
Complex(7).real #=> 7 Complex(9, -4).real #=> 9
如果 self
是使用 極座標 建立的,傳回的值會經過運算,且可能不精確
Complex.polar(1, Math::PI/4).real # => 0.7071067811865476 # Square root of 2.
VALUE rb_complex_real(VALUE self) { get_dat1(self); return dat->real; }
傳回 `false`;為了與Numeric#real?
相容。
static VALUE nucomp_real_p_m(VALUE self) { return Qfalse; }
傳回一個新的複數物件,由引數組成,每個引數都必須是 Numeric
的執行個體,或其子類別的執行個體:Complex、Float
、Integer
、Rational
;請參閱 直角座標
Complex.rect(3) # => (3+0i) Complex.rect(3, Math::PI) # => (3+3.141592653589793i) Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)
Complex.rectangular 是 Complex.rect 的別名。
傳回 `self`。
static VALUE nucomp_to_c(VALUE self) { return self; }
傳回值為BigDecimal
。
對於有理複數,需要 `precision` 參數。此參數用於決定結果的有效數字位數。
require 'bigdecimal' require 'bigdecimal/util' Complex(0.1234567, 0).to_d(4) # => 0.1235e0 Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
另請參閱 Kernel.BigDecimal
。
# File ext/bigdecimal/lib/bigdecimal/util.rb, line 157 def to_d(*args) BigDecimal(self) unless self.imag.zero? # to raise eerror if args.length == 0 case self.real when Rational BigDecimal(self.real) # to raise error end end self.real.to_d(*args) end
如果可能,將 self.real
的值傳回為 Float
Complex(1, 0).to_f # => 1.0 Complex(1, Rational(0, 1)).to_f # => 1.0
如果 self.imag
不完全等於零(Integer(0)
或 Rational(0, n)
),會引發 RangeError
。
static VALUE nucomp_to_f(VALUE self) { get_dat1(self); if (!k_exact_zero_p(dat->imag)) { rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float", self); } return f_to_f(dat->real); }
如果可能,將 self.real
的值傳回為 Integer
Complex(1, 0).to_i # => 1 Complex(1, Rational(0, 1)).to_i # => 1
如果 self.imag
不完全等於零(Integer(0)
或 Rational(0, n)
),會引發 RangeError
。
static VALUE nucomp_to_i(VALUE self) { get_dat1(self); if (!k_exact_zero_p(dat->imag)) { rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer", self); } return f_to_i(dat->real); }
傳回代表 self
的 JSON
字串
require 'json/add/complex' puts Complex(2).to_json puts Complex(2.0, 4).to_json
輸出
{"json_class":"Complex","r":2,"i":0} {"json_class":"Complex","r":2.0,"i":4}
# File ext/json/lib/json/add/complex.rb, line 48 def to_json(*args) as_json.to_json(*args) end
如果可能,將 self.real
的值傳回為 Rational
Complex(1, 0).to_r # => (1/1) Complex(1, Rational(0, 1)).to_r # => (1/1)
如果 self.imag
不完全等於零(Integer(0)
或 Rational(0, n)
),會引發 RangeError
。
static VALUE nucomp_to_r(VALUE self) { get_dat1(self); if (!k_exact_zero_p(dat->imag)) { rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", self); } return f_to_r(dat->real); }
傳回 self
的字串表示法
Complex(2).to_s # => "2+0i" Complex('-8/6').to_s # => "-4/3+0i" Complex('1/2i').to_s # => "0+1/2i" Complex(0, Float::INFINITY).to_s # => "0+Infinity*i" Complex(Float::NAN, Float::NAN).to_s # => "NaN+NaN*i"
static VALUE nucomp_to_s(VALUE self) { return f_format(self, rb_String); }