今さら丸めの話

265=36893488147419103232の次に大きいIEEE64bit浮動小数点数は265+213=36893488147419111424です。仮に、265+212+1=36893488147419107329を浮動小数点数に丸めるとしたら、IEEE754を持ち出すまでもなく表現できる中で最も近い浮動小数点数に丸めるのが自然でしょうから、265+213になるはずです。では実際に試してみましょう。

$ php -r 'printf("%21.0f\n",36893488147419107329);'
 36893488147419111424
$ perl -e 'printf("%21.0f\n",36893488147419107329);'
 36893488147419103232
$ ruby -e 'printf("%21.0f\n",36893488147419107329);'
 36893488147419103232
$ python -c 'print "%21.0f\n" % 36893488147419107329;'
 36893488147419103232

ふむふむ。きむら(K)さんの書いている strtod、round の話はおいておいて、うちの環境でも試してみよう。

% cat test.sh
#!/bin/sh

echo 'integer literal'
echo -n 'php4  '; php4   -r 'printf("%21.0f\n",36893488147419107329);'
echo -n 'php5  '; php5   -r 'printf("%21.0f\n",36893488147419107329);'
echo -n 'perl  '; perl   -e 'printf("%21.0f\n",36893488147419107329);'
echo -n 'ruby  '; ruby   -e 'printf("%21.0f\n",36893488147419107329);'
echo -n 'python'; python -c 'print "%21.0f\n" % 36893488147419107329;'

echo 'floating literal'
echo -n 'php4  '; php4   -r 'printf("%21.0f\n",36893488147419107329.0);'
echo -n 'php5  '; php5   -r 'printf("%21.0f\n",36893488147419107329.0);'
echo -n 'perl  '; perl   -e 'printf("%21.0f\n",36893488147419107329.0);'
echo -n 'ruby  '; ruby   -e 'printf("%21.0f\n",36893488147419107329.0);'
echo -n 'python'; python -c 'print "%21.0f\n" % 36893488147419107329.0;'

% sh test.sh
integer literal
php4   36893488147419110000
php5   36893488147419110000
perl   36893488147419103232
ruby   36893488147419111424
python 36893488147419111424

floating literal
php4   36893488147419110000
php5   36893488147419110000
perl   36893488147419103232
ruby   36893488147419103232
python 36893488147419111424

うぇ。全然違う結果が出ております。
で、まぁそれぞれの言語で適当に仮数部のビット列を求めてみたりするわけです。

import sys

def significand(f):
    f = float(f)

    while 1.0 < f:
        f /= 2.0

    if f == 1.0: return (1,)

    ret = []

    while f > 0:
        f *= 2
        if f >= 1.0:
            ret.append(1)
            f -= 1.0
        else:
            ret.append(0)
    return ret


if __name__ == '__main__':
    print ''.join(str(i) for i in significand(sys.argv[1]))
<?php
function significand($f) {
    while ($f > 1.0) {
        $f /= 2.0;
    }

    if ($f == 1.0) {
        return array(1);
    }

    $ret = array();
    while ($f > 0.0) {
        $f *= 2;
        if ($f >= 1.0) {
            $ret[] = 1;
            $f -= 1.0;
        }
        else {
            $ret[] = 0;
        }
    }
    return $ret;
}

echo implode('', significand(doubleval($argv[1]))), "\n";
?>
use strict;
use warnings;
use Perl6::Say;

sub significand {
    my $f = shift;

    while ($f > 1.0) {
        $f /= 2.0;
    }

    return 1 if $f == 1.0;

    my @ret;

    while ($f > 0.0) {
        $f *= 2.0;

        if ($f >= 1.0) {
            push @ret, 1;
            $f -= 1.0;
        }
        else {
            push @ret, 1;
        }
    }

    return @ret;
}

if ($0 eq __FILE__) {
    say join '', significand($ARGV[0]);
}
def significand(f)
   while f > 1.0
      f = f / 2.0
   end

   return [1] if f == 1.0

   ret = []
   while f > 0.0
      f *= 2.0
      if f >= 1.0
         ret << 1
         f -= 1.0
      else
         ret << 0
      end
   end

   return ret
end

if $0 == __FILE__
   puts [significand(ARGV[0].to_i).join, significand(ARGV[0].to_f).join].join(' ')
end

Ruby は整数リテラル浮動小数点数リテラルで結果が違ったのでそれぞれテスト。
で、

% cat test2.sh
echo -n 'php4   '; php4    significand.php 36893488147419107329
echo -n 'php5   '; php5    significand.php 36893488147419107329
echo -n 'python '; python  significand.py  36893488147419107329
echo -n 'perl   '; perl    significand.pl  36893488147419107329
echo -n 'ruby   '; ruby    significand.rb  36893488147419107329

% sh test2.sh
php4   10000000000000000000000000000000000000000000000000001
php5   10000000000000000000000000000000000000000000000000001
python 10000000000000000000000000000000000000000000000000001
perl   1
ruby   10000000000000000000000000000000000000000000000000001 1

実際には正規化されるので、ぞれぞれ先頭の1は内部的には保持してないんだけど、まぁそれは本質的な話ではないのでおいておいて、出力結果は違っても実は内部的には同じ数字なんじゃあるまいか(Perl 除く)。id:hnw さんのところではどうなるだろう。
一応、id:hnw さんにならって環境を晒し。libc は glibc-2.3.6。

% uname -mrs
Linux 2.6.18-4-xen-amd64 x86_64

% perl -v

This is perl, v5.8.8 built for x86_64-linux-gnu-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

% python -V
Python 2.5.1

% ruby -v
ruby 1.8.6 (2007-06-07 patchlevel 36) [x86_64-linux]

% php4 -v
PHP 4.4.4-8+etch4 (cli) (built: Jun 30 2007 14:58:42)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies

% php5 -v
PHP 5.2.0-8+etch7 (cli) (built: Jul  2 2007 20:43:26)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies