C#で計算時の切り上げ・切捨て・四捨五入を行う方法

投稿日:2018-01-18

普段使わないと馴染みが薄いですが、日常で行う計算にも切り上げ・切捨て・四捨五入は割りと使われていたりします。
今回はそんな計算のお話。

例えば、クルマ購入時の端数の切捨てとかね。
「千円の位を負けてくれない?」みたいな感じで。
細かい買い物する時とかに、ざっくり端数を切り上げたり、切り捨てたりして概算することもあるでしょ。

それです。

しかし、この便利さゆえに、PGで扱うには少々厄介なところもある訳です。

なんで今更、四則演算を振り返るの?

なんでこんなに種類を使い分けないといけないんだよ・・・
と嘆きつつ、金額関連の処理をコーディングする必要が発生したのでやらざるを得ない。

今更って感じもするんだけど、修正しているプログラムで使い分けなきゃいけない所があったので、改めて調べてみた。
特に、お金を扱うプログラムだと、小数点以下の端数の違いが積み重なって、数円単位の誤差になる。

誤差が許されない世界がある

で、金額の誤差が出ると、お客さんにど叱られる訳ですw
数円とはいえ、誤差は誤差なので、場合によっては、初期入力のデータから値の洗い出しが発生したりします。
マジで泣けます。

数円なんて、誰かのポケットマネーとかで補填しちゃえばいいじゃない?
って思うでしょ。
やっちゃ駄目なんですよ・・・

自分は簿記資格を持ってるわけじゃないですが、確定申告で必要になる複式簿記の世界になると、入ったものと出たものが同じにならないといけないので。
なので、誤差が出るということは、何かが足りないか、過剰に記録されてしまっているということで。

コンビニでバイトなんかしてるとその時間帯のレジ担当者が自腹で補填なんていう話も聞いたりしますが、それが許されない世界もあるとうことで。

しかも会社によって違ったりする

これも、マジかよ・・・って思うんですが、会社によっては処理ごとに切り上げ・切捨て・四捨五入を使い分けるところもあるので、修正する時にその選択を間違えると、当然お客さんにドヤされますw

巨大な物とかだと、どんぶり勘定(ではないけど)で端数部分(㌧に対しての㌘単位とか)は無視したりするところもあります。

身近なところだと、車とか。
燃費を気にして、入れるガソリンの量とか気にしたりするけど、車に乗せる荷物のなかの本1冊とか、一緒に持ってるスマホとか気にしないでしょ。

そんな感じ。

切り上げ

1.5 → 2
のように小数点以下の端数を繰り上げます。
1.3でも2。
1.9でも2。

double i = 0;

//2になる
i = Math.Ceiling(1.3);

//2になる
i = Math.Ceiling(1.9);

//-1になる
i = Math.Ceiling(-1.5);

切り上げは、そう難しい事も無いので、自分でロジックも組めたりします。
C#ではMath.Ceiling()で実現できますが、言語によっては用意されていなかったり、Mathクラスが使わせてもらえなかったりで、自分で似たような関数を作ることもあります。

唯一気をつけないといけないのは、負の値の場合。

「-1.5」は「-2」ではなく、「-1」なんです。

切捨て

さて、次は切り捨てです。

切り上げとは逆なので、イメージはしやすいかと。

1.5 → 1
のように小数点以下を切り捨てます。
1.3でも1。
1.9でも1。

double i = 0;

//1になる
i = Math.Truncate(1.3);

//1になる
i = Math.Truncate(1.9);

//-1になる
i = Math.Truncate(-1.5);

切捨ては、そう難しい事も無いので、自分でロジックも組めたりします。
C#ではMath.Truncate()で実現できますが、言語によっては用意されていなかったり、Mathクラスが使わせてもらえなかったりで、自分で似たような関数を作ることもあります。

唯一気をつけないといけないのは、負の値の場合。

「-1.5」は「-2」ではなく、「-1」なんです。

四捨五入

さて、次は四捨五入です。

切り上げと切り捨てをミックスした感じです。
感じのとおり、0.4以下を切り捨てて、5以上を切り上げます。

1.5 → 2
のように小数点以下を四捨五入します。
1.3は1。
1.9は2。

double i = 0;

//1になる
i = Math.Round(1.3);

//2になる
i = Math.Round(1.9);

//-1になる
i = Math.Round(-1.3);

//-2になる
i = Math.Round(-1.9);

四捨五入も、そう難しい事も無いので、自分でロジックも組めたりします。
C#ではMath.Round()で実現できますが、言語によっては用意されていなかったり、Mathクラスが使わせてもらえなかったりで、自分で似たような関数を作ることもあります。

気をつけないといけないのは、負の値の場合。
整数と値の増減方向が変わるので、思考のループから抜け出せなくなる事もw
普段は意識して使わないけれど

まとめ

切り上げ・切捨て・四捨五入なんて、実生活で改めるまでも無く使ってる。
ただ、それが日常生活レベルなら、計算の誤差も丼勘定でOK。

プログラムをやる上では、避けて通れないので、改めて理解しておいて損は無い。
多分、正の値の時は問題ないんだけど、負の値になったときに途端にあやふやになる人が多いと思うので。







-C#

関連記事

VisualStudioでデータテーブルの中身確認できるの便利すぎワロタw

DataSetビジュアライザーで、DataTableの中身が確認できるのが便利すぎたのでメモ。 データテーブルって気軽に使えるけど、中身の確認がしち面倒くさい件 本当のところはどうなのか?ってのは知ら …

[Oracle]破棄されたオブジェクトにアクセスできません。 オブジェクト名 ‘oracleconnection’ です。

破棄されたオブジェクトにアクセスできません。 オブジェクト名 ‘oracleconnection’ です。 破棄されたオブジェクトかどうかの判断(MSDK) MSDNでも破棄さ …

Excelでシートをコピーする時に、「名前が既に存在します。」と言われるのを回避して、Excel出力を早くしたい。

結論から書いてしまうと、名前の重複を削除しても、Excelの出力は別に早くならなかった。 早くなるという意味だと、手動でシートをコピーした時に、いちいちダイアログの対応をしなくて済むので、自分で作業し …

DLLのプロパティのブロック解除をして、ダウンロードしたプログラムを起動出来るようにする。ダウンロードしたプログラムが実行できない時の対処法。

よくありますよね・・・ 予期せぬエラーってなんだよ(`・∀・´) 特にお客さんの目の前で「デンッ!!」っていうエラー音と共に表示された時の微妙な空気感がたまりません (╹◡╹) (^ω^) :(;゙゚ …

ORACLEでTO_CHARを使用し、カンマ区切りデータを出力する

帳票出力を行うPGで困った。 数値形式のデータのため、カンマ区切りで表示したいんだけど、テンプレートの制約のせいで上手く行かなくて時の解決方法。 帳票のテンプレートとなるファイルのセルは文字列形式。 …


カテゴリー