[PHP-users 5157] Re: 少数の指数表記について

HIGASHI Taku php-users@php.gr.jp
Fri, 01 Feb 2002 10:22:48 +0900 (JST)


From: "tekkyo" <tekkyo@naver.co.jp>
Subject: [PHP-users 5144] Re: 少数の指数表記について
Date: Thu, 31 Jan 2002 17:06:15 +0900 (JST)
Message-ID: <20020131081205.DE87F478@ns1.php.gr.jp>

tekkyo> >sprintfなりnumber_formatなりで文字列化した後、文字列の終端側から
tekkyo> >↓こんな感じで、余分なのを捨てちゃって下さい。
tekkyo> >
tekkyo> >  echo ereg_replace("[\.]*0+$", "", sprintf("%f", $cal));
tekkyo> 
tekkyo> これだとこれはないだろうって思われる小数点以下を指定しないとだめですよね?
tekkyo> それに以下のパターンだと
tekkyo> <?
tekkyo> $cal= 1.0000000001;
tekkyo> echo sprintf("%.20f",$cal);
tekkyo> ?>
tekkyo> 1.00000000010000000827
tekkyo> 
tekkyo> ・・・。
tekkyo> sprintfの使い方間違ってるのかな?
tekkyo> もうちょっと考えてみます。
tekkyo> いろいろありがとうございました。

出典は定かではありませんが、浮動小数点数の精度は
   float   6桁
   double 15桁
だったはず。
# %fの出力が6桁で切られるのはこの為かも?

これを念頭に、こんなテストプログラムを書いてみました。
--
<?php
print<<<END
<table border="1">
 <tr>
  <th>\$cal</th>
  <th>echo</th>
  <th>prinf("%f");</th>
  <th>printf("%.15f")</th>
  <th>ereg</th>
END;

$cal = 1;
for ($i = 0; $i < 15; $i++) {
  $cal /= 10.0;
  echo " <tr>\n";
  $fmt = sprintf("%%.%df", $i + 1);
  echo "  <td>" . sprintf($fmt, $cal) . "</td>\n";
  echo "  <td>" . $cal . "</td>\n";
  echo "  <td>" . sprintf("%f", $cal) . "</td>\n";
  echo "  <td>" . sprintf("%.15f", $cal) . "</td>\n";
  echo "  <td>" . ereg_replace("[\.]*0+$", "", sprintf("%.15f", $cal)) . "</td>\n";
}

$cal = 1;
for ($i = 0; $i < 15; $i++) {
  $cal /= 10.0;
  echo " <tr>\n";
  $fmt = sprintf("%%.%df", $i + 1);
  echo "  <td>" . sprintf($fmt, $cal + 1) . "</td>\n";
  echo "  <td>" . ($cal + 1) . "</td>\n";
  echo "  <td>" . sprintf("%f", $cal + 1) . "</td>\n";
  echo "  <td>" . sprintf("%.15f", $cal + 1) . "</td>\n";
  echo "  <td>" . ereg_replace("[\.]*0+$", "", sprintf("%.15f", $cal + 1)) . "</td>\n";
}

echo "</table>\n";
?>
--
実行結果を見ていただければ、一目瞭然で、%.15fであれば
問題なさそうです。
# 因みに %.16f では誤差があらわれます。

以上、ご参考まで