Crazy Code to Calculate 1/√x [English Subtitles]

Поділитися
Вставка
  • Опубліковано 19 гру 2024

КОМЕНТАРІ •

  • @ヘッドホン-n9f
    @ヘッドホン-n9f Місяць тому +223

    最後の「忘れろ」が趣深い

  • @NE-fy9cj
    @NE-fy9cj Місяць тому +277

    平方根はlogにすると計算しやすくて、一方floatのlogを取ってlog(1+x)のマクローリン展開による近似を適用すると上手いこと元の数のlongが現れて、さらにニュートン法で精度を高くしてるのか
    もうこれ書いた人機械語話せる数学者やろ

    • @collectedby8655
      @collectedby8655 Місяць тому +115

      このプログラムを書いた人も起源は知らずに使っていて、本当の元はどっかの大学の数学者だったはずです。その論文は有名になりませんでしたがゲームのような誤差があまり気にならないプログラムでは有用で、ソフトウェア会社で代々受け継がれていたとかだった気がします。

    • @ossss2985
      @ossss2985 Місяць тому +31

      @@collectedby8655 やっぱ数学者って神だわ

    • @Anonymous-qx6xp
      @Anonymous-qx6xp Місяць тому +3

      logの底は2なのでマクローリン展開とかではないんじゃないかな

    • @ccxxii7816
      @ccxxii7816 Місяць тому +10

      ​@@Anonymous-qx6xp 底の変換でも結局log(e,2)の定数で割ってるだけだし、割となんとかなりそう

    • @NE-fy9cj
      @NE-fy9cj Місяць тому +7

      ⁠​⁠@@Anonymous-qx6xp
      確かにと思って調べてみたら
      0< x=m/2^23

  • @t.s.55
    @t.s.55 Місяць тому +168

    16億くらいの定数のところに書いてある
    “// what the fuck?”がおもろい

    • @可児風我
      @可児風我 Місяць тому +15

      //なんこれ?

    • @Asakoto1849
      @Asakoto1849 Місяць тому +7

      ​@@可児風我コメントであることを示す記号

    • @inti-lime61
      @inti-lime61 Місяць тому +54

      @@Asakoto1849 いやまて、what the fuckを日本語訳しただけにも見える。。。

    • @Asakoto1849
      @Asakoto1849 Місяць тому +7

      @@inti-lime61 そうでしたか…

  • @名字名前-s8t
    @名字名前-s8t Місяць тому +110

    想像より数倍変態的なコードだった
    floatの仕様の中身に手つっこんで裏技にしてるなんて…

  • @y_nene
    @y_nene Місяць тому +38

    Inverse square rootで検索したらWiki立ってるのかよこのアルゴリズム……
    気の狂った遺物マジで大好き

  • @ぬぺ
    @ぬぺ Місяць тому +43

    数学と機械計算をグチャグチャにしていいとこどりしたコード好きだ

  • @こんにちは-g3u6b
    @こんにちは-g3u6b 25 днів тому +8

    今まで見た高速逆平方根の説明で一番分かりやすかったです。
    意外と解析?されていたんですね。

  • @TM-so3co
    @TM-so3co 19 днів тому +4

    ゆっくり解説の中で、1番簡潔でわかりやすい動画だと思う

  • @rice_Place
    @rice_Place Місяць тому +31

    この話知った時、このチャンネルで解説してくれないかなあと思ったので助かります

  • @Russelii
    @Russelii Місяць тому +10

    高速逆平方根の解説他でも見たけど難しかったけど、
    えびまラボさんの解説は無駄がない非常に簡潔だし、とてもわかり易かったです!
    むしろえびまラボさんでも8分かかるくらいの難しい話ってことか

  • @TNTSuperMan-Developers
    @TNTSuperMan-Developers Місяць тому +9

    そのWTFな逆平方根関数気になってました!
    プログラミングの勉強になりました!(ならない)
    解説ありがとうございます!

  • @大野ひろき-y7w
    @大野ひろき-y7w Місяць тому +14

    変態ということだけ知ってたけど、ちゃんとした理屈があるってことに感動した。

  • @qaultyo008
    @qaultyo008 Місяць тому +9

    分子動力学の多重極子展開などで3次元座標にある2点間距離の逆乗を高速に求めたい時につかってました
    lapacあたりにも実装があった気がする
    あと数列の加速法とか補間あたりの分野も標本の数を変えずに予測精度を上げれんの?というワクワク感ありますよね。

  • @aqua_length
    @aqua_length Місяць тому +10

    Inverse Square Rootだ!だいすきです!
    5:13
    知ってるだろうがでふふってなりました。

  • @Coda-2
    @Coda-2 Місяць тому +24

    マジックナンバー!
    ちょっと前にショート動画で見たやつだ
    floatの中身がそのまま使えるなんてよく気付いたよなぁ...

  • @collectedby8655
    @collectedby8655 Місяць тому +25

    ポインタでキャストする理由は普通にキャストすると整数と小数の内部表現に合わせてキャストされますが、
    (1->1.0のように)
    ポインタでキャストすることで内部のbitそのままに型を変換できるからですね。

    • @とっぽ-x8g
      @とっぽ-x8g Місяць тому +7

      ポインタでのキャストはstrict aliasing ruleに反するので未定義動作ですね。
      ちゃんと実装するのであれば、C言語ならunionが使えます。
      C++の場合はunionでの変換も未定義動作なので、C++17以前はmemcpy、それ以降はstd::bit_castが使えます (コンパイラの最適化により実際にコピーは行われません)

    • @collectedby8655
      @collectedby8655 Місяць тому +13

      @@とっぽ-x8g 僕に言われても困りますが💦
      動画のソースコードにもコメントでevil floating point bit level hackingって書いてありますね。

    • @soul_fb9990
      @soul_fb9990 Місяць тому

      @@とっぽ-x8g std::bit_castの存在知らんかったから助かる……
      memcpy使って処理したら処理速度落ちるし、reinterpret_cast使ったら未定義動作だし……で妥協して無理やりキャストしてたのでマジで助かる

    • @nickfero
      @nickfero Місяць тому +3

      memcpyはバイト単位の操作だからたぶん遅くなる。
      もちろん32bitアラインされたポインタ専用のmemcpyを作ればいいけどそれはもうC++じゃない
      とかなんとかいってるけどそういうことを分かったうえで無理してて
      しかも役に立ってるのがこの話のミソ
      普通は無理してもほとんど効果なくてバグるだけだから「忘れろ」

  • @おれっち-s9o
    @おれっち-s9o Місяць тому +16

    なるほどlogを取ることで√の操作を1/2倍に置き換えることができるのか
    肝心のlogの操作は浮動小数点数の表記をそのまま整数として読めばできるから時間を短縮できると

  • @星雲男子大学
    @星雲男子大学 Місяць тому +7

    こういう、floatとかの「仕様」を利用した変態コードは、別環境に移植したときに(つまり仕様が変わったときに)正しく動作しなくなる可能性があるので、手放しで真似するのはやめましょう。
    組み込みプログラミングとかで「別環境への移植」が考えられない場合や、
    IEEEなどの規格を厳密に守られていることが保証されている環境間の移植しかありえない場合などは使えるので、そういったことを事前に検討してから使いましょう。

  • @0408ranko
    @0408ranko Місяць тому +14

    数学あるある証明を丁寧に解説してくれれば理解は出来るけど思い付くわけないだろシリーズ

    • @あい-l7u5p
      @あい-l7u5p 27 днів тому

      記録って偉大だよね
      後世の化学者は常に「強くてニューゲーム」できる

    • @かにざ-g8m
      @かにざ-g8m 21 день тому +2

      記録を読むだけで寿命尽きちゃう定期

  • @A0ikun1818
    @A0ikun1818 Місяць тому +12

    ちょうど1/√x+1/√y

  • @tatao5649
    @tatao5649 Місяць тому +1

    超絶わかりやすい~!

  • @TumoiYorozu
    @TumoiYorozu Місяць тому +23

    rsqrt 命令と掛け算命令さえあれば、rsqrt(x) × x で sqrt(x) の代わりになったり、rsqrt(x) の2乗で1/x が求められたりと、2命令だけで sqrt も div も実現できてお得(sqrt も div も本来とても複雑な回路)

  • @Anonymous-qx6xp
    @Anonymous-qx6xp Місяць тому +3

    1+m/2^23が0以上1未満だから、e=floor(log2(y))+127、m/2^23=y*2^(127-e)-1で、i/2^23=e+m/2^23を具体的にyで表すことができる。Excelか何かでグラフを作ってみるとlog2(y)+Cを区分的に直線で表した関数になるのがよくわかる

  • @tof1418
    @tof1418 Місяць тому +12

    このアルゴリズムホント好き

  • @YOU-ur8vo
    @YOU-ur8vo Місяць тому +5

    ほんとこれ天才

  • @lydialitvyak7750
    @lydialitvyak7750 Місяць тому +3

    コメントの
    what the fuck?
    が好きすぎる

  • @renyoko
    @renyoko Місяць тому +4

    これが何に使われてるのかをちゃんと説明してくれるの地味にありがたい、照明の処理に使われているけど詳しいことは省くって言うだけで終わらせることもできるだろうに…

  • @aiokazaki3695
    @aiokazaki3695 18 днів тому +2

    3:48「意外と複雑じゃなかった」
    ワイ「…?」

  • @ててて-k2y
    @ててて-k2y Місяць тому +4

    キモすぎと気持ち良いが同時に来る

  • @分子軌道法
    @分子軌道法 Місяць тому +13

    近似ってセンスやなあ

  • @saka1029
    @saka1029 Місяць тому

    Javaだとlongのビット幅とか浮動小数点のフォーマットが決まっているので、可搬性が高い。
    static float Q_rsqrt(float number) {
    final float threehalfs = 1.5F;
    float x2 = number * 0.5F, y = number;
    long i = Float.floatToIntBits(y);
    i = 0x5f3759df - (i >> 1);
    y = Float.intBitsToFloat((int)i);
    y = y * (threehalfs - (x2 * y * y));
    y = y * (threehalfs - (x2 * y * y));
    return y;
    }

  • @andrew8128
    @andrew8128 Місяць тому +4

    3:23 これ、初めて知ったときちょっと感動したのを思い出した。

  • @八木士
    @八木士 Місяць тому +3

    ニュートン法は収束が早いってどっかで聞いたことがあるけどほんとに速いんだなあ

  • @あさひ-o8z
    @あさひ-o8z Місяць тому +2

    これは気持ちいい……

  • @匿名匿名-p9m
    @匿名匿名-p9m Місяць тому +1

    1/√xで思い出したんですが、グラフィック系のシェーダープログラミングだと、rand関数がないので色々工夫して代用しているらしいです。それに関連してメルセンヌツイスターとかXORシフトあたりの乱数生成の解説も聞いてみたいです!ここ最近WGSLでパストレーサーを実装しようとしてるんですが、有名なfract-sinの擬似乱数だと周期性が気になるので他のアルゴリズムも知りたいと思ってます。

  • @しお-p5w
    @しお-p5w Місяць тому +18

    このcastはstrict aliasing ruleに反し、未定義動作となるため、正しく動作する保証がないことには注意する必要がありますね。Cではunionを使うのが正しいですね。

  • @CakeCh.
    @CakeCh. Місяць тому +1

    これの応用で立方根を求める手法もありますよね。

  • @仮名ろはん
    @仮名ろはん 3 дні тому

    確かに変態コードなんだけど、ここまでするならもっと開き直って、入射光に大~小5段階くらいのパラメータを割り振って、その大小関係を反射光にも反映、でいい気がする・・・

  • @N-EMPRESSEUR
    @N-EMPRESSEUR Місяць тому +3

    flootをlogの近似でlongに救出してニュートン法で帳尻合わせ、数値解析の演習でやりましたねえ
    もしかして数値計算やる人も、実はそんなに気にしていない・・・・・・?

  • @sy476
    @sy476 Місяць тому +39

    実際今のCPU命令に√計算あるんでもう忘れて良いやつ

    • @aconite0988
      @aconite0988 Місяць тому +1

      中身はもしかして同じようなことしてるのかな?

    • @resistan-y1h
      @resistan-y1h Місяць тому +3

      マイコンとか組み込み系では使えそう。

    • @ああ-r9e1d
      @ああ-r9e1d Місяць тому

      @@resistan-y1hこれ

  • @s009kawa
    @s009kawa Місяць тому +1

    対数だと計算が楽
    昔はコンピューターさんも計算尺を使っていたんですね

  • @enkero-q2c
    @enkero-q2c Місяць тому +19

    7行テトリスについて解説して欲しいです!

    • @evimalab
      @evimalab  Місяць тому +21

      リクエストありがとうございます!お約束はできませんが、年内に出そうとしてみます。

  • @NumAniCloud
    @NumAniCloud 28 днів тому +2

    そ、そうか……! 指数の情報が直接メモリに書かれているのだから、logを求めるのは容易……!なんてエレガントなんだ
    αとかいう定数について考えるのはやめておきます

  • @kaba3889
    @kaba3889 24 дні тому

    これが天才か

  • @mekuri5767
    @mekuri5767 Місяць тому +1

    正規表現の微分について解説してほしいです!

  • @lolipuni1
    @lolipuni1 Місяць тому

    天才は居る

  • @takek9215
    @takek9215 13 днів тому +2

    感動するが、実務でこんなコードを書いてはいけない。
    誰もメンテできなくて休日どころか退職後も呼び出される可能性がある。

  • @ofoneDyag
    @ofoneDyag Місяць тому

    &yのアドレスがfloatポインタ型だから、それをlongポインタ型にキャストした上で間接参照することで、yの中身自体もfloatからlongにキャストできるってことか?

  • @ルーカス-k1r
    @ルーカス-k1r Місяць тому +4

    精度の比較だけじゃなくて,実際の計算速度の比較も気になる

    • @soul_fb9990
      @soul_fb9990 Місяць тому +13

      今のコンピュータでやってもあんまり効果は感じられないと思う。
      当時の掛け算割り算のコストがバカ高いコンピュータだからこそ価値がある感じのコード。
      弥生土器とかを見てロマンに浸ってる感じ。
      この動画は
      「昔は穴の中で火を焚べてたから縦長で重心低いんだなぁ」
      って紹介してる感じ。現代は平たいコンロで十分。

    • @ルーカス-k1r
      @ルーカス-k1r Місяць тому +2

      @ なるほど!

  • @totto2727
    @totto2727 Місяць тому +3

    longのビット数って実行環境によって変わらなかったっけ…(32か64になることがほとんどだったと思いますが…)

    • @とっぽ-x8g
      @とっぽ-x8g Місяць тому +4

      そうですね、uint32_tを使うのが最適だと思います。
      floatと整数型のキャストも未定義動作なので、実際にはmemcpyなどを使う必要がありますね

    • @ccxxii7816
      @ccxxii7816 Місяць тому +1

      そもそもこのコード自体32bit時代の話で独自命令も乏しかったらしいし、現代じゃ最初のチルノの書き方が何周も回って速くて確実なんだっけ?

  • @Asakoto1849
    @Asakoto1849 Місяць тому

    x2 = number*0.5F;
    ってあるけど、ビットハック使って
    long temp;
    temp = *(long*)&number;
    temp -= 0x800000;
    x2 = *(float*)&temp;
    にすれば速くなるかな

  • @yamonton_9945
    @yamonton_9945 Місяць тому +3

    解説されればまぁ分かる(分からん)のだけどこれをゼロから思いつくのは無理
    思考ルートが分からん

  • @kerokeroq
    @kerokeroq Місяць тому +1

    ある文字(二進数の組み合わせ)で表現された数字のlogをとったらその文字そのものが含まれてて、マジックナンバーはその残り物ってこと?

  • @まんま-l8f
    @まんま-l8f 15 днів тому

    変態すぎる

  • @誰かさん-e1b
    @誰かさん-e1b 25 днів тому

    昔のプログラミングはこんな考え方がてんこ盛りだったよね。懐かしい。

  • @user-777ntl
    @user-777ntl Місяць тому

    むずかしい…

  • @アルト-b7w
    @アルト-b7w Місяць тому +2

    floatってどこから指数なのかどこで調べるの?

    • @KawaiiNegi-
      @KawaiiNegi- Місяць тому +4

      区切りが決まってる

    • @とっぽ-x8g
      @とっぽ-x8g Місяць тому +5

      C/C++におけるfloatは実装定義なので、残念ながら一般的な方法はありません。
      ただし、ほとんどの処理系ではfloatはIEEE754に従っているので、それを仮定すればよいです。
      C23/C++23以降であれば、それぞれIEEE754に従うことが規定されている _Float32, std::float32_t がありますが、そこまで気にする必要はないです

    • @星雲男子大学
      @星雲男子大学 Місяць тому +1

      IEEEと呼ばれる「ルール」がある。

  • @凡人-l9l
    @凡人-l9l Місяць тому

    このコードが初めてのCでしたはーと❤

  • @明賀葵
    @明賀葵 Місяць тому

    面白い

  • @water-bondrewd
    @water-bondrewd 7 днів тому

    longって符号付き64bitでは???

  • @angiodianxin
    @angiodianxin Місяць тому +8

    03:35 の「ケチだね」、ふふってなる

  • @user-yuuyuu1729
    @user-yuuyuu1729 Місяць тому

    詳しくは分からんけど、すげぇってことは分かった.
    よく気がつくなぁ...

  • @hitsuki_karasuyama
    @hitsuki_karasuyama Місяць тому

    高速逆平方根アルゴリズム

  • @うめはち橙
    @うめはち橙 Місяць тому

    高速逆平方根!

  • @d1Prczr6b29eM82Y
    @d1Prczr6b29eM82Y Місяць тому

    世の中のエンジニアってこれをぱっと理解できるのか 土方には無理だなやっぱ

  • @たろう-o7n
    @たろう-o7n 17 днів тому

    高速逆平方根きもちよすぎだろ!

  • @毛糸-c7l
    @毛糸-c7l Місяць тому +1

    こんなのよく気づくなあ

  • @quartzhammar
    @quartzhammar Місяць тому +3

    日本語のはずなのに99.8%くらいわかんねぇ…

    • @大喜-n6y
      @大喜-n6y Місяць тому +5

      半分くらいはC言語やけどもな

  • @ioritobeta6293
    @ioritobeta6293 10 днів тому

    きm...(褒め言葉)

  • @zouo-from-Taikonotatsujin
    @zouo-from-Taikonotatsujin Місяць тому +4

    マジックナンバーは誤差吸収で
    真の技術結晶はマジックナンバー書いてある行のyの計算だったってこと?

  • @セイゲドン
    @セイゲドン Місяць тому +1

    中田敦彦のモノマネしながらコレ解説する奴好き

  • @あい-d5f6q
    @あい-d5f6q Місяць тому +2

    「結果が分かりやすいし⑨で」

    • @匿名希望-z3n
      @匿名希望-z3n Місяць тому +2

      ぶっちゃけここのチルノは賢い……

  • @yattinda
    @yattinda Місяць тому

    なるほどわからん

  • @Garlic014-
    @Garlic014- 9 днів тому

    なに言ってるかわからん笑笑

  • @libraplanet
    @libraplanet 28 днів тому +1

    進数は人間が読むための数値の書式の話であり、量とは関係ない。ビットは2進数に様相が似ているだけで、2進数ではない。変数には値があり、そこにはビットで表現されており、進数は関係ない。コンピューターの値が2進数と言うひどい嘘があって、ただの数学の話なんだなぁと思った。