From: "kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core" <ruby-core@...> Date: 2023-05-14T03:01:27+00:00 Subject: [ruby-core:113470] [Ruby master Bug#5179] Complex#rationalize and to_r with approximate zeros Issue #5179 has been updated by kjtsanaktsidis (KJ Tsanaktsidis). I've explored the behaviour here a bit, and I think I do believe that `0.0` really does represent the concept of "zero". Specifically, it's the number that satisfies the following properties, for all possible non-NaN floats N: * `abs(0.0 * N) == 0.0` * `0.0 + N == N` You might obtain a bit pattern for 0.0 from the result of a calculation which might have otherwise produced a non-zero result if there was more precision; however that doesn't change the fact that the bit pattern you have really does satisfy the mathematical properties of zero. Additionally, I think the distinction that complex.c currently draws between floating-point and non-floating-point zero also results in some other surprising results: ``` irb(main):030:0> Complex(3, 7) ** 0.0 => (1.0+0.0i) irb(main):031:0> Complex(3, 7) ** 0 => (1+0i) irb(main):032:0> Complex(3.2, 7) ** 0 => (1+0i) irb(main):033:0> Complex(3.2, 7) ** 0.0 => (1.0+0.0i) ``` Why does the type of `A ** B` depend on whether B is a float or not, but not A? ``` irb(main):034:0> Complex(3.2, 7) ** Complex(1, 0.0) => (3.200000000000001+6.999999999999999i) irb(main):035:0> Complex(3.2, 7) ** Complex(1, 0) => (3.2+7i) ``` This doesn't _need_ to accumulate floating point error - the code in `rb_complex_pow` special-cases `(a + bi) ** (c + 0i) -->(a + bi) ** c`, but the special-casing is skipped if `0i` is `0.0i` instead. Also, `#to_i` and `#to_f` have the same issue as `#to_r`: ``` irb(main):037:0> Complex(3, 0.0).to_i (irb):37:in `to_i': can't convert 3+0.0i into Integer (RangeError) irb(main):038:0> Complex(3, 0.0).to_f (irb):38:in `to_f': can't convert 3+0.0i into Float (RangeError) ``` This is especially odd for `#to_i` because it of course has no problems truncating away the real part: ``` irb(main):040:0> Complex(3.1, 0).to_i => 3 ``` I think we should change all the checks for `k_exact_zero_p` in `complex.c` to `f_zero_p`; i.e. in all the places where `complex.c` special-cases integer zero, also make it special-case floating-point zero. If people agree with this (especially people who actually use Complex in their code - I have pretty much never used it!) I can send a pretty simple patch to cloe this out. ---------------------------------------- Bug #5179: Complex#rationalize and to_r with approximate zeros https://bugs.ruby-lang.org/issues/5179#change-103049 * Author: marcandre (Marc-Andre Lafortune) * Status: Assigned * Priority: Normal * Assignee: mrkn (Kenta Murata) * ruby -v: r32354 ---------------------------------------- Currently, Complex#rationalize and Complex#to_r raise a RangeError if the imaginary part is nonzero *or is a Float*. Note that a BigDecimal(0) is accepted, though: Complex(1, 0).to_r # => Rational(1,1) Complex(1, BigDecimal("0.0")).to_r # => Rational(1,1) Complex(1, 0.0).to_r # => RangeError This is inconsistent. I recommend not raising an error for 0.0 (Float or BigDecimal). Any objection? -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/