ã¼ãã®ããããããããããã®roundé¢æ°
æµ®åå°æ°ç¹æ°ã®ä¸¸ãã«ããã¦ä¸¸ãæ¡æ°ãæå®ã§ããããã§ãã¦ç²¾åº¦ã失ããªããããªroundé¢æ°ãCã§å®è£ ãã¦ã¿ã¾ããã
å®è£ ã¨ãã¦ã¯ãåãåã£ãæµ®åå°æ°ç¹æ°ããæçã«ãªã10é²è¡¨è¨ã«å¤æããæµ®åå°æ°ç¹ããºã©ããã¨ãªã10é²è¡¨è¨ã®ã¾ã¾åæ¨äºå ¥ãè¡ããã®ã§ãããããå ã«å¶æ°ä¸¸ããå®è£ ããã®ã容æã§ãããã
å®éãååè¨äºãRubyとPythonとC#のround関数のバグっぽい挙動についてãã§ææãã5.015ã®ä¾ã«ã¤ãã¦ãæå¾ éãã«ä¸¸ãããã¨ãã§ãã¾ãã
#include <stdio.h> extern double precise_round(double x, int digits); int main() { printf("%f\n", precise_round(5.015, 2)); // 5.02 printf("%f\n", precise_round(5.0149999999999987921, 2)); // 5.01 }
æµ®åå°æ°ç¹æ°ã¨ãã®10é²è¡¨è¨ã®æ£ç¢ºãªç¸äºå¤æã¯1990å¹´ã®è«æã§æ±ºçæ¸ã¿
æµ®åå°æ°ç¹æ°ã¨ãã®10é²è¡¨è¨ã¨ã®éã§æãè¿ãæ°ã«å¤æããæ¹æ³ã¯ãHow to Read Floating Point Numbers Accurately *1ããHow to Print Floating-Point Numbers Accurately *2ãã¨ããè«æã§ç¤ºããã¦ãã¾ããã¾ãããã®è«æãå ã«ãã¦David M. Gayが実装したdtoa.cã¯ãå¤ãã®ãªã¼ãã³ã½ã¼ã¹ããã¸ã§ã¯ãã§å©ç¨ããã¦ãã¾ãã
ååè¨äºã§ç´¹ä»ããMySQLã®å¦çã§ãæµ®åå°æ°ç¹æ°ããæçã®10é²è¡¨è¨ãä½ãåºãã¦ãã¾ããããã®å¦çã«ã¯ä¸è¨dtoa.cã®æ¹å¤çãå©ç¨ããã¦ãã¾ããã¡ãªã¿ã«åã®ä»åã®å®è£ ã¯ãªãªã¸ãã«ã®dtoa.cããã®ã¾ã¾å©ç¨ãã¾ããã
æµ®åå°æ°ç¹æ°ãªãã©ã«ãæµ®åå°æ°ç¹æ°ã«ç´ãå¦çã§ãä¼¼ãè°è«ããã£ã
å®ã¯ä»¥åã®è¨äºãPHP以外全員不正解ããRubyの浮動小数点数リテラルの扱いは正しいのかããMySQLの自前strtod実装がタコすぎるãã«ããã¦ãä¼¼ããããªè©±é¡ãããã¾ããããããã®è¨äºã§ãä¸é¨ã®è¨èªãããã«ã¦ã§ã¢ã§ã¯æµ®åå°æ°ç¹ãªãã©ã«ãæè¿æ¥ã®æµ®åå°æ°ç¹æ°ã«å¤æã§ãã¦ããªããã¨ããææããã¾ããã
ãããã¯ã©ããèªåã§å°æ°ç¹ããããå¦çãè¡ã£ã¦ããã10.0åãç¹°ãè¿ãããã¨èª¤å·®ãèç©ããããªããã¤ã¼ããªå®è£ ã«ãªã£ã¦ãã¾ãããææ°çã§ã¯ä¿®æ£ããã¦ä¸è¨dtoa.cã®ææãå©ç¨ãã¦ãããã®ãã»ã¨ãã©ã ã¨æãã¾ãã
åã¯ãä»åã®åè¨èªã®roundé¢æ°ã®å®è£ ãåæ§ã«ãã¤ã¼ããªå®è£ ã ã¨æãã¾ãããã¾ãããã¤ã¼ããªå®è£ ãçã¿åºã誤差ãé¿ããããªã誤差ã¨ãã¦åãæ¢ãã¦ãã人ãä¸å®æ°ããæ°ããã¦ããããã®æå³ã§ãé常ã«ä¼¼ã¦ããã¨æãã¾ãã
ä»åã®roundé¢æ°ãåè¨èªãå®è£ ãã¹ããã©ããã«ã¤ãã¦
çµè«ããè¨ãã¨ãåè¨èªã®roundé¢æ°ãä»åä½ã£ããããªæ£ç¢ºãªå¦çã«ãªã£ã¦ããå¿ è¦ã¯ãªãã¨æãã¾ããã¨ããã®ããroundé¢æ°ã¯ç²¾åº¦ãè½ã¨ãæ¼ç®ãªã®ã§ãããã§å¤å°ã®èª¤å·®ãæ··å ¥ããã¨ããã§è´å½çãªèª¤å·®ã®èç©ã«ã¯ã¤ãªãããªãã¨èããããããã§ããã¾ããæµ®åå°æ°ç¹æ°ãªãã©ã«ãæµ®åå°æ°ç¹æ°ã«ããå¦çã¨ç°ãªããä½ãã®ä»æ§ã§æ£ç¢ºãã«ã¤ãã¦ã®è¦è«ãããããã§ãããã¾ããã
ã¤ã¾ããåå人ã¨ãã¦ã¯ãããã¥ã¢ã«ã«å®è£ ãæè¨ãã¦ããã°ã©ããªå®è£ ã§ãããããããªããã¨æã£ã¦ãã¾ããä¸ä¸å°ã人ããããèªåå®è£ ãããã10é²åãæ¡ç¨ããã°ããããã§ããã
ã¨ã¯ãããç¡ç¨ãªèª¤å·®ãçã¿ãã¡ãªã®ã§ãæµ®åå°æ°ç¹ããããã¦æ»ããããªå¦çãè¦ããæãã¨æãããã¨ã¯éè¦ã ã¨æãã¾ããã¾ããè¨èªå®è£ ããããããªäººãåãç´æãæã£ã¦ããã¯ãã ã¨æãã®ã§ãåè¨èªã§ä¸æ£ç¢ºãªå®è£ ã«ãªã£ã¦ããã®ãæå¤ã«æããã¨ããã®ãååè¨äºãæ¸ãããã£ããã§ããã
*1:William D Clinger, "How to Read Floating Point Numbers Accurately", ACM SIGPLAN '90, pp.92--101, 1990. ï¼同じ論文のretrospective版のPDF版ï¼
*2:Guy L. Steele, Jr. and Jon L. White, "How to Print Floating-Point Numbers Accurately", ACM SIGPLAN '90, pp.112--126, 1990. ï¼同じ論文のretrospective版のPDF版ï¼