3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

bignumber.jsの使い方 ~Javascriptの小数での計算の誤差をなくすライブラリ~

Last updated at Posted at 2021-10-25

はじめに

これは、bignumber.jsのメソッドなどの備忘録です。
小数の計算に悩んでいた方の役に立てると幸いです。

実行環境

BigNumber.jsのバージョン: v9.0.1
テストしたブラウザ:
Google Chrome 95.0.4638.54(Official Build) (x86_64)

bignumber.jsとは

Javascriptで小数の計算をすると、丸め誤差というものが発生してしまう場合があります。

console.log(0.1 + 0.2); //0.30000000000000004

0.3になるはずなのですが、誤差が出てきてしまいます。
Javascriptでこのような計算をせず、サーバーサイドに任せるのが最適かもしれませんが、どうしてもの場合に、 bignumber.js を使います。

なぜ誤差がでてくるのか

コンピュータ内部で小数を2進数に変換したときに、循環小数などになってしまい近似値を使わなければならなくなるためです。詳しくはこのサイトを参照してください。

インストール

npm(Node.js)でインストールできます。

npm install bignumber.js

または、Githubからダウンロードできます。

git clone https://github.com/MikeMcl/bignumber.js.git

bignumber.jsを使う

1. bignumber.jsを読み込む

ブラウザで読み込む:

<script src="./path/bignumber.js" type="text/javascript">

または、

<script type="module">
import BigNumber from './path/bignumber.mjs';
...
</script>

Node.jsを使う:

const BigNumber = require('bignumber.js');

2. 数を定義する

Object型なので、浮動小数点型よりは面倒です。
いくつか宣言方法があります。

let num = new BigNumber(0.1);
console.log(num.toString()); //'0.1'

//その他の宣言方法
BigNumber(0.1); //'0.1' newは省略可能
new BigNumber('32e-5'); //'0.00032' 指数表記も可能
new BigNumber(1101, 2); //'13' 基数2を指定
new BigNumber('123.456'); //'123.456' 文字列値から生成

newは省略することができて、指数表記を使うことができます。
基数(n進法のnの数字のこと)を第2引数に指定することもできます。

3. 基本の演算

注意
普通の演算子を使用することはできません。

//足し算
BigNumber(0.1).plus(0.2); //'0.3'

//引き算
BigNumber(0.1).minus(0.2); //'-0.1'

//掛け算
BigNumber(0.1).times(0.2); //'0.02'

//割り算
BigNumber(0.1).div(0.2); //'0.5'

//商の整数部
BigNumber(0.1).idiv(0.03); //'3'

//割ったときのあまり
BigNumber(0.1).mod(0.03); //'0.01'

//累乗
BigNumber(0.1).pow(2); //'0.01'

基本的な算術演算です。
関数名が長いものには短縮形の関数もあります。
上は全て短縮形です。
くわしくはこちらを参照してください(英語です)。

また、

BigNumber(0.3) - BigNumber(0.2); //'0.09999999999999998'

とやってもうまく動かないのでやらないようにしましょう。

4. その他のメソッド

1. 絶対値

abs()を使う。戻り値はBigNumber

BigNumber(-0.1).abs(); //'0.1'

2. シフト(小数点を動かすこと)

shiftedBy(n)を使う。戻り値は、BigNumber

BigNumber(0.123).shiftedBy(3); //'123'
BigNumber(12.3).shiftedBy(-2); //'0.123'

3. 平方根

sqrt()を使う。戻り値は、BigNumber。丸められる。
丸める設定をするのは後述します。

BigNumber(0.01).sqrt(2); //'0.1'
BigNumber(0.1).sqrt(2); //'0.3162277660168379332'

4. 正負の逆転

negated()を使う。戻り値は、BigNumber

BigNumber(0.4).negated(); //'-0.4'
BigNumber(-4.6).negated(); //'4.6'

5. BigNumberを比べるメソッド

1.大小どちらも

comparedTo(n [, 基数])を使う。([]内は書いても書かなくても良い引数)
戻り値は、Number

戻り値について:

戻り値 大小
1 BigNumberがnよりも大きい
-1 BigNumberがnよりも小さい
0 BigNumberとnがおなじ
null BigNumberかnがNaN
BigNumber(3.5).comparedTo(2.6); //1
BigNumber(2.8).comparedTo(BigNumber(6.5)); //-1
BigNumber(-1.3).comparedTo(-1.3); //0
BigNumber(4.6).comparedTo(NaN); //null

2.等しいかどうか

.eq(n [,基数])を使う。戻り値はBoolean
NaN同士を比べても、falseになります。

BigNumber(0.1).eq(0.2); //false
BigNumber(255).eq('ff', 16); //true
BigNumber(NaN).eq(BigNumber(NaN)); //false

3.不等号たち

gt(n [,基数])などを使う。戻り値はBoolean
他の関数もおなじ引数でおなじ戻り値です。

BigNumber(0.1).gt(0.3); // > BigNumberのほうがnより大きい false
BigNumber(0.1).gte(0.1); // >= BigNumberはn以上 true
BigNumber(0.1).lt(0.2); // < BigNumberのほうがnより小さい true
BigNumber(0.3).lte(0.1); // >= BigNumberはn以下 false

6. 〜をであるかを調べるメソッド

1. BigNumberかを調べる

isBigNumber(value)を使う。戻り値はBoolean

BigNumber.isBigNumber(3); //false
BigNumber.isBigNumber(BigNumber(3.5)); //true
BigNumber.isBigNumber(BigNumber(NaN)); //true

2. 整数かを調べる

isInteger()を使う。戻り値はBoolean

BigNumber(123.456).isInteger(); //false
BigNumber(123).isInteger(); //true

3. NaNかを調べる

isNaNを使う。戻り値はBoolean

BigNumber(Math.sqrt(-1)).isNaN(); //true
BigNumber(3).isNaN(); //false

4. 正負を調べる

BigNumber(3.5).isPositive(); //true 正かどうかを調べる
BigNumber(-0).isNegative(); //true 負かどうかを調べる
BigNumber(13).isZero(); //false 0かどうかを調べる

7. BigNumberを他の型に変換

Numberへ

toNumber()を使う。戻り値はNumber

BigNumber(4.2).toNumber(); //4.2

Stringへ

toString([基数])またはtoFixed([小数点以下の桁数 [, 丸めモードの指定]])を使う。戻り値はString
丸めモードは、後述します。

BigNumber(3.4).toString(); //'3.4'
BigNumber(2).toString(2); //'10'
BigNumber(6.7).toFixed(); //'6.7'
BigNumber(34.6157984).toFixed(3); //34.616

分数へ(BigNumberの配列)

toFraction([n])を使う。戻り値は[BigNumber, BigNumber]
引数のnには、最大の分母を指定することができます。
その場合は、最大の分母を超えないように近づけたものが返されます。

BigNumber(1.45).toFraction(); //['29', '20']
const x = new BigNumber(3.14159265358979);
x.toFraction();//['314159265358979','100000000000000']
x.toFraction(100); //['311', '99']

丸めモードの設定

BigNumber.set()またはBigNumber.config()を使う。
どちらも全く同じことをやっています。

詳しくはサンプルコードを参照してください。

BigNumber(1).div(3); //'0.33333333333333333333'
BigNumber.set({
    DECIMAL_PLACES : 5, //小数点以下の最大桁数
    ROUNDING_MODE : BigNumber.ROUND_UP //丸める方法(切り上げ)
});
BigNumber(1).div(3); //'0.33334'

設定項目はもっといっぱいありますが、ここで取り上げるもの
(丸めモードに関係があるもの)以外は公式ドキュメントをご覧ください。

ROUNDING_MODEに入る値
(数直線でイメージしてください。マイナスの場合の対応です。)

キーワード 説明
ROUND_UP 0 切り上げ(0から離れていく)
ROUND_DOWN 1 切り下げ(0へと近づいていく)
ROUND_CEIL 2 切り上げ(正の方向へと行く)
ROUND_FLOOR 3 切り下げ(負の方向へと行く)
ROUND_HALF_UP 4 四捨五入(0から離れていく)
ROUND_HALF_DOWN 5 四捨五入(0へと近づいていく)
ROUND_HALF_EVEN 6 基本は四捨五入だが、5の場合には、偶数になる方に丸められる。
ROUND_HALF_CELL 7 四捨五入(正の方向へと行く)
ROUND_HALF_FLOOR 8 四捨五入(負の方向へと行く)

ちなみに、デフォルトではDECIMAL_PLACES: 20
ROUNDING_MODE: ROUND_HALF_UPです。

BigNumberを丸める

dp([n[, 基数]])を使う。戻り値は、nを指定した場合はBigNumber,
指定しなかった場合はNumber

nを指定した場合は、小数点以下のn桁目までを残して、
ROUNDING_MODEに従い丸められます。
nを指定しなかった場合には、小数点以下が何桁あるかを返します。

BigNumber(3.515145).dp(3); //'3.515'
BigNumber.config({ROUNDING_MODE: BigNumber.ROUND_CEIL});
BigNumber(3.515145).dp(3); //'3.516'

BigNumber(3.515145).dp(); // 6

BigNumberを整数に丸める

integerValue([基数])を使う。戻り値はBigNumber
丸めモードに従って丸められる。

BigNumber(2.51798).integerValue(); //'3'(ROUND_HALF_UP)

BigNumberそのものを複製する

BigNumber.clone()を使う。戻り値は、BigNumberコンストラクタ。
BigNumber.config() (BigNumber.set()) が複雑になるときにこうすると良いです。

BigNumber.set({ROUNDING_MODE: BigNumber.ROUND_FLOOR});
const copy = BigNumber.clone();
copy.config({ROUNDING_MODE: BigNumber.ROUND_CEIL});
//このように省略できます。
//BigNumber.clone({ROUNDING_MODE: BigNumber.ROUND_CEIL});
BigNumber(1.564635).dp(5); //'1.56463'
copy(1.564635).dp(5); //'1.56464'

参考リンク

  • BigNumber公式API

  • BigNumberのGitHubリポジトリ

  • Qiitaの記事

  • 誤差について

おわりに

この記事でほとんどのメソッドなどを紹介しましたが、一部紹介していないものもあります。
使いみちがあまりなさそうだ、と勝手に判断したものですが、公式ドキュメントなどを参考にして読んでみてください。また、誤りがありましたら、コメント欄にてお知らせしていただけると嬉しいです。

3
1
1

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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?