hnwの日記

浮動小数点数

ECMAScriptの浮動小数点数の丸め仕様がスゴい

ECMAScriptの浮動小数点数の丸め関数である Number.prototype.toFixed() について調べてみたところ、浮動小数点数をわかっている人が作った硬派な仕様だと感じたので、解説してみます。 浮動小数点数の丸めの善し悪しについて 私はプログラミング言語の浮動…

MySQLのFLOAT型を使う理由が見つからない件

MySQLのデータ型としてFLOAT型という型があるのですが、これを採用するのは混乱の元ではないか?と感じたので、その詳細を紹介します。 そもそもこの話のきっかけは「MySQLで6桁までの小数点を丸めずに扱うならFLOAT型を使うべき理由」という記事が目に止ま…

PHPのround関数とは一体なんだったのか

(7/3 14:05追記)Javaに関する記述について誤認があったので盛大に書き換えました。Java 6、Java 7、Java 8それぞれで実装が変わっていたようです。(7/13 23:55追記)本記事中ではroundを四捨五入と言い切ってしまっています。これは筆者がC99のroundを基…

Monoで巨大な浮動小数点数を丸めたら無限大になった

Monoのround関数にバグを見つけたよ、という毎度おなじみの話題です。 早速ですが、浮動小数点数で扱える一番大きい数を浮動小数点数以下第2位で丸めて第1位までにしてみましょう。 using System; class RoundingBigFloat { static void Main() { double d =…

C#のdecimalからdoubleへのキャストにバグを見つけた気がする

C#の丸めは基本的に偶数丸め(banker's rounding)だというのが僕の認識ですが、decimalの数をdoubleにキャストするときに四捨五入になる例がありました。また、.NET環境に限り最近接のdoubleに丸められない例も見つけました。 decimalからdoubleへのキャス…

ぼくのかんがえたさいきょうのround関数

浮動小数点数の丸めにおいて丸め桁数を指定でき、それでいて精度を失わないようなround関数をCで実装してみました。 https://github.com/hnw/precise-round 実装としては、受け取った浮動小数点数から最短になる10進表記に変換し、浮動小数点をズラすことな…

RubyとPythonとC#のround関数のバグっぽい挙動について

(12/29 20:40追記)「(追記)なぜMySQLのdecimal型を例に使ったかについて」というセクションを追加しました。また、コメントを頂戴したので返信しました。 (12/29 21:30追記)C#について言えば「Math.Round メソッド (Double, Int32)」に内部実装がどうなっ…

第70回PHP勉強会で浮動小数点数の話をしました

7月22日に開催された第70回PHP勉強会で発表してきました。以下が発表資料です。 浮動小数点数周りのトピックを3点紹介する内容でしたが、思ったより反応が良かったように思います。 ただ、面白おかしく話そうとして、聞いている方々に無駄に恐怖を与えてしま…

MySQLの自前strtod実装がタコすぎる

MySQL5.1のソースコードを確認していたところ、浮動小数点数の10進表記から浮動小数点数への変換処理に実装上の問題点を見つけました。浮動小数点数処理の典型的な落とし穴にはまっていて、計算の途中で精度を落としてしまっています。 これは古くから知られ…

MySQL5.1以降の小数の扱いがキモい

穏やかな昼下がりにMySQLで小数の足し算をしていたところ、不思議な現象を見つけました。 mysql> select 0.8=0.7+0.1; +-------------+ | 0.8=0.7+0.1 | +-------------+ | 1 | +-------------+ 1 row in set (0.00 sec) mysql> select 0.8=0.7+0.1e0; +----…

浮動小数点数の丸め処理を見比べてみる

各種プログラミング言語には、切り上げ・切り捨て・四捨五入など浮動小数点数を丸める関数が何種類もあります。こうした丸め処理を利用する際、「ceilとfloorどっちがどっちだっけ?」「マイナスの数が来た時の挙動って大丈夫なんだっけ?」などと不安になる…

PHPの新しいround関数を読み解く (2)pre-roundingの意味

(2011/10/18 01:50)「他の言語で試してみる」「誰が正しいのか?」を追記しました。また、初心者への対策と強調しすぎて誤解を招いた気がしたため、少し表現を変更しました。 前回記事「PHPのround関数を読み解く (1)丸め桁数が大きすぎ・小さすぎる場合」に…

PHP5.3.4から5.3.6までのround関数がときどき丸めすぎてたのが直った

PHP5.3.4から5.3.6のround関数に問題があるんじゃないか、と僕がバグ報告していた件(PHP :: Bug #54334)が、PHP5.3.7から修正されています。僕のバグレポには特に返事もないので、全く独立に修正されたんだと思います。PHP5.3.7のChangeLogには次のような…

PHPのround関数を読み解く (1)丸め桁数が大きすぎ・小さすぎる場合

PHPのround関数はPHP5.3.0で一新されましたが、その挙動は複雑です。以前の記事「PHP5.3.0alpha3のround関数の実装がPHP5.2.6と変わった」では典型的な挙動を紹介しましたが、実際はもう少し細かい場合分けがあります。僕自身の整理も兼ねて、RFC*1およびPHP…

PHPの新しいround関数にバグをみつけた

PHP 5.3.0以降、PHPのround関数の挙動はChristian Seilerさんが提案したRFCに従って一新されています。この新しいround関数の仕様上の問題もしくはバグを見つけました。 以前の記事「PHP5.3.0alpha3のround関数の実装がPHP5.2.6と変わった」でこの新しい実装…

Pythonのround関数で奇数を丸めたら偶数になった

Pythonのround関数にバグらしきものを見つけたよ、という報告です。下記は僕のMacBookでの実行結果です。 $ python -c 'x=9007199254740991.0; print "%.19f\n%.19f" % (x, round(x))' 9007199254740991.0000000000000000000 9007199254740992.0000000000000…

Rubyのround関数の実装が変わってた

今週は国際浮動小数点数ウイークですので、週の最後もやはり浮動小数点数ネタです。 Rubyのround関数の実装に関して、1.8.6 patchlevel 114と1.8.6 patchlevel 230の間に変更が入っています。1.8.6-p230のリリース時期は2008/06/20のようですから、1.8.7(20…

PHPの浮動小数点数の表示

PHPのround関数のリファレンスマニュアルのページに面白いコメントを見つけたので紹介します。

roundとprintfの丸めに関する不整合

さて、先日の記事「PHP5.3.0alpha3のround関数の実装がPHP5.2.6と変わった」でも紹介したPHPのround関数を改善する提案には、printfとの整合性についても書かれています。というのも、printfで"%.2f"などと精度を指定した場合、round関数と同様に丸めが発生…

PHP5.2.7のround関数の実装もPHP5.2.6と変わった

題名の通り、PHP5.2.7でround関数の実装が変更されました。12月8日付でPHP5.2.8がリリースされましたが、round関数についてはPHP5.2.7と同一です。 概要 ますがたさんの記事で既報ですが、bugs #42294に関してPHP5.2.7で修正が入り、round関数の実装が変わり…

PHP5.3.0alpha3のround関数の実装がPHP5.2.6と変わった

(2016/07/02 20:00追記)本稿をさらに掘り下げた記事「PHPのround関数を読み解く (1)丸め桁数が大きすぎ・小さすぎる場合」「PHPの新しいround関数を読み解く (2)pre-roundingの意味」を書きました。合わせてご確認ください。 12月4日付でPHP5.2.7とPHP5.3.0a…

iPhoneアプリの浮動小数点数が気になる

iPhone買う買う言ってたくせに発売されたら全然買わない人って居ますよね。そう、僕のことです。買う買う詐欺ですね。 そんな、興味があるんだか無いんだかわからないiPhoneですけど、「夏の50連発!! これが定番iPhoneアプリだ(前編)」という記事を見てい…

近況報告

つい先ごろroundの話題を読み直してみました。自分で言うのもアレですが中々面白いですね。ただ、今になってみると無駄にムキになっている自分に気づきます。 どういうことかというと、自分でも最初は「PHPってイカれてるでしょ、わはは」ってつもりで書いて…

Rubyの浮動小数点数リテラルの扱いは正しいのか

題名の通りなんですが、前回の記事「PHP以外全員不正解」に対して「ダウト!」を頂戴したのでまとめてみます。 Cのこの動作が、唯一無二絶対のものであるとする根拠はどこにあるのでしょうか? strtod によれば、 If the subject sequence has the decimal fo…

PHP以外全員不正解

いまだにround関数のまとめは出来ていません。そろそろ皆様に忘れられる前にまとめなきゃな、とは思っていますが、もうしばらくお待ちください。今回は微妙にround関数と近いような遠いような話題です。 巨大な数の丸めについて実験しているうちに、PHPだけ…

round関数その9:PerlのMath::Roundモジュールについて

少なくとも十数人は居ると思われる読者の皆様、ごぶさたしておりました。サボリのため、まとめ記事は全く書けていません。 さて、今回は他所の記事の紹介です。PerlのMath::RoundというモジュールにPHPと似たようなマジックナンバーが採用されているようです…

round関数その8:RubyとPythonのround関数は奇妙じゃないんですか?

さて、今回はRubyとPythonの題名をつけてしまいましたけど、それらの言語だけに限らないような話題です*1。早速ですが、FreeBSD環境を用意してください(おそらくSPARC Solaris環境やMac OS X環境でも同じ結果だろうと思いますが、僕は確認していません)。 …

round関数その7:偶数丸め

いい加減まとめるか他の記事書けよって感じですが、まだまだround関数の続きです。実際のところ僕も結構飽きていたりします。 この一連のround関数の件について言及している記事を見ると、かなり怪しい知識レベルの人もいるように思います。そんな記事をいち…

round関数その6:啓蒙とお詫び

Referer一覧の存在に気づいたので、リンクして下さっている方々の文章を今更読んでいます。ただ、おそらく浮動小数点数の扱いが拙いのをround関数のせいにしているような文章を見つけました。もしそういう誤解があれば非常に残念だと思うと同時に、これだけ…

round関数その5:そろそろ反撃していいですか?

さて、またまた「PHPの奇妙なround関数」の続きです。今回はタイトルからいきなり負けそうですけど、気にせずいきましょう。 Matzさんの記事に反論するにはかなり理論武装が必要だろうという考えから、ここ2回の記事は僕としても頑張って書いてきました。た…