四元数平方根


11

背景

四元数是扩展复数的数字系统。四元数具有以下形式

a+bi+cj+dk

其中a,b,c,d是实数,i,j,k是三个基本四元数单元。这些单位具有以下属性:

i2=j2=k2=1
ij=k,jk=i,ki=j
ji=k,kj=i,ik=j

注意,四元数乘法不是可交换的

任务

给定一个非实四元数,请至少计算其平方根之一。

怎么样?

根据此Math.SE答案,我们可以用以下形式表示任何非实四元数:

q=a+bu

其中a,b是实数,而uxi+yj+zk形式的虚数单位向量,其中x2+y2+z2=1。任何此类u都具有u2=1,因此可以将其视为虚数单位。

然后,q的平方如下所示:

q2=(a2b2)+2abu

反之,给定四元数q=x+yu,我们可以通过求解以下方程式找到q的平方根

x=a2b2,y=2ab

这与查找复数的平方根的过程相同。

请注意,负实数具有无限多个四元数平方根,但非实四元数仅具有两个平方根

输入输出

输入是非实四元数。您可以选择任意顺序和结构将其视为四个实数(浮点数)。非实数表示b,c,d中的至少一个非零。

输出是一个或两个四元数,平方时等于输入。

测试用例

   Input (a, b, c, d)  =>  Output (a, b, c, d) rounded to 6 digits

 0.0,  1.0,  0.0,  0.0 =>  0.707107,  0.707107,  0.000000,  0.000000
 1.0,  1.0,  0.0,  0.0 =>  1.098684,  0.455090,  0.000000,  0.000000
 1.0, -1.0,  1.0,  0.0 =>  1.168771, -0.427800,  0.427800,  0.000000
 2.0,  0.0, -2.0, -1.0 =>  1.581139,  0.000000, -0.632456, -0.316228
 1.0,  1.0,  1.0,  1.0 =>  1.224745,  0.408248,  0.408248,  0.408248
 0.1,  0.2,  0.3,  0.4 =>  0.569088,  0.175720,  0.263580,  0.351439
99.0,  0.0,  0.0,  0.1 =>  9.949876,  0.000000,  0.000000,  0.005025

使用此Python脚本生成。每个测试用例仅指定了两个正确答案之一。另一个是所有四个值都取反。

得分和获胜标准

适用标准规则。每种语言中最短的程序或函数(以字节为单位)获胜。


我们可以把四元数当作a, (b, c, d)吗?
nwellnhof

@nwellnhof好的。即使这样a,[b,[c,[d]]]也可以,如果您可以通过某种方式保存字节的话,:)
Bubbler

Answers:



8

Python 2,72个字节

def f(a,b,c,d):s=((a+(a*a+b*b+c*c+d*d)**.5)*2)**.5;print s/2,b/s,c/s,d/s

在线尝试!

或多或少的原始公式。我以为我可以使用列表推导式遍历b,c,d,但这似乎更长。由于缺乏向量运算,尤其是缩放和规范,Python确实受到了伤害。

Python 3,77个字节

def f(a,*l):r=a+sum(x*x for x in[a,*l])**.5;return[x/(r*2)**.5for x in[r,*l]]

在线尝试!

直接解决二次问题也比使用Python的复数平方根来解决问题要短。


“输入是一个非实四元数。您可以选择任意顺序和结构将其当作四个实(浮点)数。” 因此,您可以将其视为pandas系列或numpy数组。系列具有简单乘法的缩放比例,并且有多种获取范数的方法,例如(s*s).sum()**.5
累积


4

JavaScript(ES7),55 53字节

基于xnor使用的直接公式。

将输入作为数组。

q=>q.map(v=>1/q?v/2/q:q=((v+Math.hypot(...q))/2)**.5)

在线尝试!

怎么样?

q=[a,b,c,d]

x=a+a2+b2+c2+d22

并返回:

[x,b2x,c2x,d2x]

q =>                            // q[] = input array
  q.map(v =>                    // for each value v in q[]:
    1 / q ?                     //   if q is numeric (2nd to 4th iteration):
      v / 2 / q                 //     yield v / 2q
    :                           //   else (1st iteration, with v = a):
      q = (                     //     compute x (as defined above) and store it in q
        (v + Math.hypot(...q))  //     we use Math.hypot(...q) to compute:
        / 2                     //       (q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2) ** 0.5
      ) ** .5                   //     yield x
  )                             // end of map()

3

Haskell,51个字节

f(a:l)|r<-a+sqrt(sum$(^2)<$>a:l)=(/sqrt(r*2))<$>r:l

在线尝试!

直接公式。表示输出的实部r/sqrt(r*2)与虚部表达式平行的主要技巧是,它在以下方面节省了一些字节:

54字节

f(a:l)|s<-sqrt$2*(a+sqrt(sum$(^2)<$>a:l))=s/2:map(/s)l

在线尝试!


3

木炭,32字节

≔X⊗⁺§θ⁰XΣEθ×ιι·⁵¦·⁵η≧∕ηθ§≔θ⁰⊘ηIθ

在线尝试!链接是详细版本的代码。@xnor的Python答案的端口。说明:

≔X⊗⁺§θ⁰XΣEθ×ιι·⁵¦·⁵η

|x+yu|=x2+y2=(a2b2)2+(2ab)2=a2+b2x2a22a

≧∕ηθ

y=2abb2a

§≔θ⁰⊘η

2a

Iθ

将值转换为字符串并隐式打印。


3

Java 8,84字节

(a,b,c,d)->(a=Math.sqrt(2*(a+Math.sqrt(a*a+b*b+c*c+d*d))))/2+" "+b/a+" "+c/a+" "+d/a

@xnor的Python 2 Answer的端口。

在线尝试。

说明:

(a,b,c,d)->           // Method with four double parameters and String return-type
  (a=                 //  Change `a` to:
     Math.sqrt(       //   The square root of:
       2*             //    Two times:
         (a+          //     `a` plus,
          Math.sqrt(  //     the square-root of:
            a*a       //      `a`  squared,
            +b*b      //      `b` squared,
            +c*c      //      `c` squared,
            +d*d))))  //      And `d` squared summed together
  /2                  //  Then return this modified `a` divided by 2
  +" "+b/a            //  `b` divided by the modified `a`
  +" "+c/a            //  `c` divided by the modified `a`
  +" "+d/a            //  And `d` divided by the modified `a`, with space delimiters

2

05AB1E,14 个字节

nOtsн+·t©/¦®;š

@xnor的Python 2 Answer的端口。

在线尝试验证所有测试用例

说明:

n                 # Square each number in the (implicit) input-list
 O                # Sum them
  t               # Take the square-root of that
   sн+            # Add the first item of the input-list
      ·           # Double it
       t          # Take the square-root of it
        ©         # Store it in the register (without popping)
         /        # Divide each value in the (implicit) input with it
          ¦       # Remove the first item
           ®;     # Push the value from the register again, and halve it
             š    # Prepend it to the list (and output implicitly)


2

C#.NET,88个字节

(a,b,c,d)=>((a=System.Math.Sqrt(2*(a+System.Math.Sqrt(a*a+b*b+c*c+d*d))))/2,b/a,c/a,d/a)

我的Java 8 answer的端口,但返回一个Tuple而不是一个String。我以为会更短一些,但是不幸的Math.Sqrt是,System在C#.NET中需要-import,最终以4字节长而不是10字节短..>>

不过,lambda声明看起来很有趣:

System.Func<double, double, double, double, (double, double, double, double)> f =

在线尝试。


1

Perl 6,49个字节

{;(*+@^b>>².sum**.5*i).sqrt.&{.re,(@b X/2*.re)}}

在线尝试!

以输入为的咖喱函数f(b,c,d)(a)。将四元数返回为a,(b,c,d)

说明

{;                                             }  # Block returning WhateverCode
     @^b>>².sum**.5     # Compute B of quaternion written as q = a + B*u
                        # (length of vector (b,c,d))
  (*+              *i)  # Complex number a + B*i
                      .sqrt  # Square root of complex number
                           .&{                }  # Return
                              .re,  # Real part of square root
                                  (@b X/2*.re)  # b,c,d divided by 2* real part
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.