LoginSignup
49
18

More than 3 years have passed since last update.

(ネタ) x ^ 3 + y ^ 3 + z ^ 3 = 42 の答えを見つけたチームがいるらしいのでJSのBigIntで確かめてみる

Last updated at Posted at 2019-09-09

概要

Twitterを眺めていたら、「Sum of three cubes for 42 finally solved -- using real life planetary computer」という記事が引用されていました。

42といえば、なんとなく気になる数字ですよね。

使われている数字が大きいので、JavaScriptのBigIntの出番です。

BigIntとは

BigIntは、JavaScriptで任意の大きな整数を扱うことができるライブラリです。
(JavaScriptの標準の数値型であるNumberで信頼できる値として扱えるのは( 2 ^ 53 - 1)まで)

このエントリを書いている時点で、TC39(Ecma International, Technical Committee 39)でStage3です。

JavaScriptエンジンのV8では実装されたものがあり、Node V10 LTS以降で利用可能になっています。

コード

GitHubに置いてあります。https://github.com/hrkt/answer42/releases/tag/1.0.0

BigIntを使うときは、BigInt(数値)としてオブジェクトを初期化するほかに、末尾に「n」をつけてBigIntであることを示すことができます。


// using BigInt(https://developer.mozilla.org/ja/docs/Web/JavaScript

exports.answer42 = function() {
    const x = -80538738812075974n
    const y = 80435758145817515n
    const z = 12602123297335631n
    return  x ** 3n + y ** 3n + z ** 3n
}

補足: 3乗を示している「**3n」 には、BigIntであることを示す「n」が必要です。BigIntとNumberの演算は、暗黙の裡に型変換されることがないため、下記のようなエラーとなります。。

    return  x ** 3 + y ** 3 + z ** 3
              ^

TypeError: Cannot mix BigInt and other types, use explicit conversions

テストしてみます。テストコードは下記です。

const assert = require('assert')
const answer = require("../answer")
describe('The answer', function() {
  describe('#answer42()', function() {
    it('should return 42', function() {
      assert.equal(answer.answer42(), 42n)
    })
  })
})

実行してみます。

PS C:\Users\work\answer42\js> npm run test 
> answer42@1.0.0 test C:\Users\work\answer42\js
> mocha



  The answer
    #answer42()
      √ should return 42


  1 passing (232ms)

答えがあっています。

テストは、これをGitHub Actionsで動かしておきます。設定は以下の通り。

name: Node CI

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x, 12.x]

    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - name: npm install, build, and test
      run: |
        (cd js; npm install)
        (cd js; npm run test)
      env:
        CI: true

Node_ci_passing.PNG

補足:Numberで計算した場合との違い

BigIntを使わず、下記のようにNumberで実行した場合と比べてみます。

// using Number(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number)
exports.answer42InNumber = function() {
    const x = -80538738812075974
    const y = 80435758145817515
    const z = 12602123297335631
    return  x ** 3 + y ** 3 + z ** 3
}

main.jsはこんな感じです。

const answer = require('./answer')
console.log("BigInt:" + answer.answer42())
console.log("Number:" + answer.answer42InNumber())

実行してみます。

PS C:\Users\work\answer42\js> npm run start

> answer42@1.0.0 start C:\Users\work\answer42\js
> node main.js

BigInt:42
Number:1.989298733926156e+35

Numberだと、生命、宇宙、そして万物についての究極の疑問の答え42とならないことがわかります。

まとめ

JavaScriptのBigIntを使い、大きな数を扱うときの例を扱いました。

補足

Wolfram Alpha様であれば実は一瞬で解けたりするのか、と思ってためしてみましたが、そんなことはありませんでした。

https://www.wolframalpha.com/input/?i=x+%5E+3+%2B+y+%5E+3+%2B+z+%5E+3+%3D+42

冒頭に引用した記事によると、分散計算用のツール"Charity Engine"を使って50万台以上のPCの「空き時間」で計算したとのこと。

49
18
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
18