2012-02-06 59 views
5

這個問題在代碼中最好的表達:問題與浮點乘法和評價

$var1 = 286.46; // user input data 
$var2 = 3646; // user input data 
$var3 = 25000; // minumum amount allowed 
$var4 = ($var1 * 100) - $var2; // = 250000 
if ($var4 < $var3) { // if 250000 < 250000 
    print 'This returns!'; 
} 

var_dump($var4)輸出:float(25000)和投時爲int,輸出:int(24999) - 從而這就是問題所在。

我真的不知道該怎麼辦它雖然。這個問題發生在乘以100後,雖然我可以做一些小技巧來解決這個問題(比如* 10 * 10),但我想知道這個問題是否存在「真正的」解決方案。

謝謝:)

+0

推薦閱讀:http://floating-point-gui.de/ – 2012-02-06 11:51:39

回答

0

這就是浮做有時,它是所有因花車怎麼都無法準確地代表整數不時。

相反,它轉換成一整型的,你可以將該數字四捨五入爲整數值,然後將其轉換爲int。 (可能是不必要的,但PHP並不清楚內部是如何發生這種情況的,即使你知道它們現在是如何發生的,它們可能在將來也是如此。)

0

我認爲你可以使用bccomp進行比較浮點值,但我認爲這是一個函數,不是在PHP的核心。

否則,我發現這個功能here但我無法測試它,看它是否工作

function Comp($Num1,$Num2,$Scale=null) { 
    // check if they're valid positive numbers, extract the whole numbers and decimals 
    if(!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num1,$Tmp1)|| 
    !preg_match("/^\+?(\d+)(\.\d+)?$/",$Num2,$Tmp2)) return('0'); 

    // remove leading zeroes from whole numbers 
    $Num1=ltrim($Tmp1[1],'0'); 
    $Num2=ltrim($Tmp2[1],'0'); 

    // first, we can just check the lengths of the numbers, this can help save processing time 
    // if $Num1 is longer than $Num2, return 1.. vice versa with the next step. 
    if(strlen($Num1)>strlen($Num2)) return(1); 
    else { 
    if(strlen($Num1)<strlen($Num2)) return(-1); 

    // if the two numbers are of equal length, we check digit-by-digit 
    else { 

     // remove ending zeroes from decimals and remove point 
     $Dec1=isset($Tmp1[2])?rtrim(substr($Tmp1[2],1),'0'):''; 
     $Dec2=isset($Tmp2[2])?rtrim(substr($Tmp2[2],1),'0'):''; 

     // if the user defined $Scale, then make sure we use that only 
     if($Scale!=null) { 
     $Dec1=substr($Dec1,0,$Scale); 
     $Dec2=substr($Dec2,0,$Scale); 
     } 

     // calculate the longest length of decimals 
     $DLen=max(strlen($Dec1),strlen($Dec2)); 

     // append the padded decimals onto the end of the whole numbers 
     $Num1.=str_pad($Dec1,$DLen,'0'); 
     $Num2.=str_pad($Dec2,$DLen,'0'); 

     // check digit-by-digit, if they have a difference, return 1 or -1 (greater/lower than) 
     for($i=0;$i<strlen($Num1);$i++) { 
     if((int)$Num1{$i}>(int)$Num2{$i}) return(1); 
     else 
      if((int)$Num1{$i}<(int)$Num2{$i}) return(-1); 
     } 

     // if the two numbers have no difference (they're the same).. return 0 
     return(0); 
    } 
    } 
} 
1

這是一個可怕的哈克解決方案,我稍微討厭自己,但是這給了預期的行爲:

<?php 

    $var1 = 286.46; // user input data 
    $var2 = 3646; // user input data 
    $var3 = 25000; // minumum amount allowed 
    $var4 = ($var1 * 100) - $var2; // = 250000 
    if ((string) $var4 < (string) $var3) { // if 250000 < 250000 
     print 'This returns!'; 
    } 

將它們轉換爲字符串,並將它們轉換回適合比較的int/float。我不喜歡它,但它確實有效。

真的需要BC Math在PHP精密浮點數學。

0

的問題是,漂浮只是不能代表一些數字。由於PHP沒有「十進制」(或其他定點)類型,因此基本上只能解決這些問題。

假設您示例中的第一個數字$var1 = 286.46表示某種貨幣,您可以在用戶輸入它之後直接將其轉換爲分(例如,通過剝離點並將其讀取爲整數),然後使用整數數學。

這不是一個通用的解決方案 - 我懷疑存在一個(短使用任意精度的數字,其中一些PHP擴展提供的 - 但我的氣味像矯枉過正對我來說)。

1

當使用浮點數作爲int時使用ceil(或基於你想要的樓層)總是一個好主意 在你的情況下,在比較之前試試ceil($ var4)!