四元数平方根


11

バックグラウンド

四元数は、複素数を拡張する数値システムです。クォータニオンの形式は次のとおりです

a+bi+cj+dk

ここa,b,c,dは実数で、i,j,kは3つの基本的な四元数単位です。ユニットには次のプロパティがあります。

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

四元数の乗算は可換ではないことに注意してください。

仕事

非実数のクォータニオンが与えられた場合、その平方根の少なくとも1つを計算します。

どうやって?

このMath.SEの回答によれば、非実数の四元数は次の形式で表現できます。

q=a+bu

ここでBは実数であり、Uは形で虚数単位ベクトルであり、xはI + Y jの+ Z KX 2 + Y 2 + Z 2 = 1。そのようなuには、プロパティu 2 = 1があるため、虚数単位と見なすことができます。a,buxi+yj+zkx2+y2+z2=1uu2=1

次に、qの二乗は次のようになります。

q2=(a2b2)+2abu

逆に、クォータニオンq=x+yu与えられると、次の方程式を解くことによりq平方根を見つけることができます。

x=a2b2,y=2ab

これは、複素数の平方根を見つけるプロセスと同じです。

負の実数には無限に多くの四元数平方根がありますが、非実数の四元数には2つの平方根しかありません

入出力

入力は非実数の四元数です。任意の順序と構造で、4つの実数(浮動小数点数)として受け取ることができます。非実数とは、b,c,d少なくとも1つが非ゼロであることを意味します。

出力は、1つまたは2つのクォータニオンであり、2乗すると入力と等しくなります。

テストケース

   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スクリプトを使用し生成されます。各テストケースに対して2つの正解のうち1つだけが指定されています。もう1つは4つの値すべてが否定されます。

採点基準

標準の規則が適用されます。各言語の最短のプログラムまたは機能がバイト単位で勝ちます。


四元数をとることはできますa, (b, c, d)か?
nwellnhof

@nwellnhof確かに。以下のようにも何かがa,[b,[c,[d]]]あなたが何とかそれでバイトを保存することができた場合、罰金です:)
バブラ

回答:


29

APL(NARS)、2 バイト

NARSには、クォータニオンの組み込みサポートがあります。¯\ _(⍨)_ /¯


4
私はそれを助けることはできません:あなたはあなたの答えに "¯_(ツ)_ /¯"を含めるべきです
Barranka

7
あなたはこれを落としました
アンドリュー

@Barranka完了。
アダム

@AndrewはAndroidアプリでそれを非難しています...それを拾ってくれてありがとう:)
Barranka

2
¯\_(⍨)√¯
それなら

8

Python 2 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の複素数平方根を使用して問題ステートメントのように解決するよりも短かったです。


「入力は非実数の四元数です。任意の順序と構造で、4つの実数(浮動小数点数)として入力できます。」だから、あなたはそれがパンダシリーズまたは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=[abcd]

バツ=a+a2+b2+c2+d22

そして戻ります:

[バツb2バツc2バツd2バツ]

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

、32バイト

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。@xnorのPython回答のポート。説明:

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

入力のすべての要素を二乗して合計を取り、次に平方根を取ります。これは計算する|バツ+yあなたは|=バツ2+y2=a2b22+2ab2=a2+b2。追加中バツ 与える 2a2 次に、2倍になり、平方根が得られます 2a

≧∕ηθ

なぜなら y=2ab、計算する b 割る 2a

§≔θ⁰⊘η

配列の最初の要素(実部)を半分に設定します 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の答え

オンラインでお試しください。

説明:

(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の答え

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

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のポートですが、文字列ではなくタプルを返します。私はそれはもっと短いだろうと思っていましたが、残念ながら、C#.NETでは-importがMath.Sqrt必要で、System10バイト短くなる代わりに4バイト長くなります。..>。>

ただし、ラムダ宣言はかなりおかしく見えます。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.