<?php
/***************************************************************************
 * Flexible Floating Point Converter
 * (C) Nico Haase 2009
 *
 * History:
 *   v0.9 (2009-02-11): Initial release
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

class BinaryFloat {
    private 
$integerBits;
    private 
$fractionBits;
    function 
BinaryFloat$input ) {
        if ( 
'' !== str_replace ( array ( '0''1''.' ), ''$input ) ) {
            throw new 
Exception $input " is no binary float!" );
        }
        list ( 
$this->integerBits$this->fractionBits ) = explode '.'$input );
    }
    
    function 
shiftLeft $shift ) {
        while ( 
strlen $this->fractionBits ) < $shift ) {
            
$this->fractionBits .= '0';
        }
        
$this->integerBits $this->integerBits substr $this->fractionBits0$shift );
        
$this->fractionBits substr $this->fractionBits$shift );
    }
    
    function 
shiftRight $shift ) {
        while ( 
strlen $this->integerBits ) < ( $shift ) ) {
            
$this->integerBits '0' $this->integerBits;
        }
        
$this->fractionBits substr $this->integerBits$shift ) . $this->fractionBits;
        
$this->integerBits substr $this->integerBits0$shift );
    }
    
    function 
shift $shift ) {
        if ( 
$shift ) {
            
$this->shiftLeft $shift );
        } else if ( 
$shift ) {
            
$this->shiftRight ( -$shift );
        }
    }
    
    function 
toInteger() {
        return (int)
$this->toFloat();
    }
        
    function 
toFloat() {
        
$result 0;
        for ( 
$count 0$count strlen $this->integerBits ); $count++ ) {
            if ( 
'1' == substr $this->integerBits$count) ) {
                
$result += pow 2strlen $this->integerBits ) - $count );
            }
        }
        for ( 
$count 0$count strlen $this->fractionBits ); $count++ ) {
            if ( 
'1' == substr $this->fractionBits$count) ) {
                
$result += pow 2, -* ( $count ) );
            }
        }        
        return 
$result;
    }
    
    function 
__toString() {
        
$result $this->integerBits '.' $this->fractionBits;
        while ( 
'0' == substr $result0) ) {
            
$result substr $result);
        }
        while ( 
'0' == substr $result, -) ) {
            
$result substr $result0, -);
        }
        
        if ( 
'.' == substr $result0) ) {
            
$result '0' $result;
        }
        if ( 
'.' == substr $result, -) ) {
            
$result substr $result0, -);
        }
        return 
$result;
    }
}


if ( !isset ( 
$_POST['input'] ) ) {
    
$_POST['input'] = '';
    
$_POST['exponent'] = '';
    
$_POST['fraction'] = '';
}
?>

<html><head><title>Flexible Floating Point Converter</title></head>
<body>
This tool allows to convert <a href = "http://en.wikipedia.org/wiki/Floating_point">Floating point numbers</a>
from their binary to human readable representation.

<form action = "<?php echo $_SERVER['PHP_SELF']; ?>" method = "post">
<table>
    <tr>
        <td><label for = "input">Input in binary representation:</label></td>
        <td><input type = "text" id = "input" name = "input" value = "<?php echo htmlentities($_POST['input']); ?>" size = 40></td>
    </tr><tr>
        <td><label for = "exponent">Length of exponent (in bits):</label></td>
        <td><input type = "text" id = "exponent" name = "exponent" value = "<?php echo htmlentities($_POST['exponent']); ?>"></td>
    </tr><tr>
        <td><label for = "fraction">Length of fraction (in bits):</label></td>
        <td><input type = "text" id = "fraction" name = "fraction" value = "<?php echo htmlentities($_POST['fraction']); ?>"></td>
    </tr><tr>
        <td colspan = 2 style = "text-align:center;"><input type = "submit" value = "Convert!"></td>
    </tr>
</table>
</form>

<?php
if ( strlen $_POST['input'] ) > ) {
    
$input $_POST['input'];
    
$exponentLength = (int)$_POST['exponent'];
    
$fractionLength = (int)$_POST['fraction'];
    if ( 
'' !== str_replace ( array ( '0''1' ), ''$input ) ) {
        echo 
'Wrong input! Only 0 and 1 is allowed!';
    } else if ( 
strlen $input ) !== ( $exponentLength $fractionLength ) ) {
        echo 
'Wrong length for exponent or fraction submitted!';
    } else {
        
$sign substr $input0);
        if ( 
== $sign ) {
            
$result '+';
        } else {
            
$result '-';
        }
        
$fraction = new BinaryFloat '1.' substr $input$exponentLength ) );
        
$exponent = new BinaryFloat substr $input1$exponentLength ) );
        
$exponentShifter $exponent->toInteger() - pow 2$exponentLength ) + 1;
        
$fraction->shift($exponentShifter);
        
$result .= $fraction->toFloat();
        
        echo 
'Decimal representation of <tt>' $input '</tt>: ' $result;
    }
}
?>

<a href = "<?php echo $_SERVER['PHP_SELF']; ?>s">sourcecode</a>

</body>