Testwiki:Reference desk/Archives/Mathematics/2023 August 18
Template:Error:not substituted
|- ! colspan="3" align="center" | Mathematics desk |- ! width="20%" align="left" | < August 17 ! width="25%" align="center"|<< Jul | August | Sep >> ! width="20%" align="right" |Current desk > |}
| Welcome to the Wikipedia Mathematics Reference Desk Archives |
|---|
| The page you are currently viewing is a transcluded archive page. While you can leave answers for any questions shown below, please ask new questions on one of the current reference desk pages. |
August 18
Code for complex square root
I'm trying to roll my own complex square root formula in a spreadsheet. (Actually, Calc has a built-in function IMSQRT which does this, but it takes strings as input and output and I'd rather use pairs of cells instead of trying to assemble and parse strings.) Our square root article gives a formula, but it has accuracy issues due to rounding when the real part is large compared to the imaginary part. For example when I use it to compute the square root of -10000000000+2i it gives 100000i rather than the more accurate value of .00001+100000i. Stack exchange gives some different formulas but they seem to have the rounding error issue as well. I was wondering if anyone knows how this is implemented in actual function libraries such as Python cmath. My own version isn't quite done, but it's turning out to be more complicated than I though it would be. --RDBury (talk) 06:36, 18 August 2023 (UTC)
- I suspect this is the same problem as loss of accuracy when solving the quadratic equation using the familiar quadratic formula; see Template:Section link. A better method is to use
- Solving for and gives rise, after expansion and elimination of , to a quadratic equation in :
- Use the positive root of this equation to find and compute (Disclaimer: I have not actually tried this out.) --Lambiam 11:13, 18 August 2023 (UTC)
- That's more or less the approach I'm taking. First compute then At this point u and v are either ±r, ±x/(2r) or 0. It's then a matter or working out which expression to use for which variable when, which sign to use, and when to use a special case to avoid division by 0. It's very easy to get the conjugate of a square root or a result that's not the principal branch. From a mathematician's point of view, you can reduce to the case where z is in the first quadrant by using and when applicable. --RDBury (talk) 12:15, 18 August 2023 (UTC)
- Here is Python-like pseudo code; test before use.
- Input: Template:Math
- Returns: Template:Math such that Template:Math is the principal square root of Template:Math
- if Template:Math:
- if Template:Math:
- return Template:Math
- return Template:Math
- if Template:Math:
- if Template:Math:
- set Template:Math
- return Template:Math
- if Template:Math:
- set Template:Math
- return Template:Math
- if Template:Math:
- set Template:Math
- set Template:Math
- if Template:Math:
- return Template:Math
- return Template:Math
- if Template:Math:
- --Lambiam 14:35, 18 August 2023 (UTC)
- In the code above, the cases Template:Math and Template:Math can be merged in an obvious way into one case Template:Math. A separate case for Template:Math would not be necessary except for the possibility that Template:Math, which would otherwise lead to the undefined division of Template:Math. But if the case Template:Math remains, the separate case for Template:Math is not needed. (However, if in practice the supplied argument is often real, keeping it may improve the efficiency.) --Lambiam 22:40, 18 August 2023 (UTC)
- Here is Python-like pseudo code; test before use.
- That's more or less the approach I'm taking. First compute then At this point u and v are either ±r, ±x/(2r) or 0. It's then a matter or working out which expression to use for which variable when, which sign to use, and when to use a special case to avoid division by 0. It's very easy to get the conjugate of a square root or a result that's not the principal branch. From a mathematician's point of view, you can reduce to the case where z is in the first quadrant by using and when applicable. --RDBury (talk) 12:15, 18 August 2023 (UTC)
- Lots of spreadsheets have an atan2 function. Presumably you could do r_out = sqrt(sqrt(r_in^2 + i_in^2)) * cos(atan2(i_in,r_in)/2) and i_out = sqrt(sqrt(r_in^2 + i_in^2)) * sin(atan2(i_in,r_in)/2). --Amble (talk) 17:09, 18 August 2023 (UTC)
- Throwing trigonometry into basic vector operations is a recipe for significant slowdown and a pile of tricky edge cases. –jacobolus (t) 17:13, 18 August 2023 (UTC)
- Actually the original question was about how it's done in polished code libraries. I was able to do some "quick and dirty" formulas myself. --RDBury (talk) 13:08, 19 August 2023 (UTC)
- The code implementing the Python function Template:Code can be seen here, lines 739–805. --Lambiam 14:23, 19 August 2023 (UTC)
- Actually the original question was about how it's done in polished code libraries. I was able to do some "quick and dirty" formulas myself. --RDBury (talk) 13:08, 19 August 2023 (UTC)