복붙노트

PHP에서 수레 비교

PHP

PHP에서 수레 비교

이 샘플 코드에서와 같이 PHP에서 두 개의 부동 소수점을 비교하고 싶습니다.

$a = 0.17;
$b = 1 - 0.83; //0.17
if($a == $b ){
 echo 'a and b are same';
}
else {
 echo 'a and b are not same';
}

이 코드에서는 $ a와 $ b가 같더라도 if 조건 대신 else 조건의 결과를 반환합니다. PHP에서 부동 소수점을 처리 / 비교하는 특별한 방법이 있습니까?

그렇다면이 문제를 해결하도록 도와주십시오.

아니면 내 서버 구성에 문제가 있습니까?

해결법

  1. ==============================

    1.당신이 이것을 좋아한다면 그들은 동일해야합니다. 그러나 부동 소수점 값의 특성은 동일한 값을 갖는 것으로 보이는 계산이 실제로 동일 할 필요는 없다는 점입니다. 따라서 $ a가 .17이고 $ b가 계산을 통해 도착하면 두 값이 같지만 값이 다를 수 있습니다.

    당신이 이것을 좋아한다면 그들은 동일해야합니다. 그러나 부동 소수점 값의 특성은 동일한 값을 갖는 것으로 보이는 계산이 실제로 동일 할 필요는 없다는 점입니다. 따라서 $ a가 .17이고 $ b가 계산을 통해 도착하면 두 값이 같지만 값이 다를 수 있습니다.

    일반적으로 부동 소수점 값을 이와 같이 평등하게 비교하지 않으려면 수용 가능한 가장 작은 차이를 사용해야합니다.

    if (abs(($a-$b)/$b) < 0.00001) {
      echo "same";
    }
    

    그런 것.

  2. ==============================

    2.먼저 빨간색 경고를 읽으십시오. http://www.php.net/manual/en/language.types.float.php. 평상시에는 수레를 비교해서는 안됩니다. 엡실론 기법을 사용해야합니다.

    먼저 빨간색 경고를 읽으십시오. http://www.php.net/manual/en/language.types.float.php. 평상시에는 수레를 비교해서는 안됩니다. 엡실론 기법을 사용해야합니다.

    예 :

    if (abs($a-$b) < EPSILON) { … }
    

    여기서 EPSILON은 매우 작은 숫자를 나타내는 상수입니다 (정의해야합니다)

  3. ==============================

    3.또는 bc 수학 함수를 사용해보십시오.

    또는 bc 수학 함수를 사용해보십시오.

    <?php
    $a = 0.17;
    $b = 1 - 0.83; //0.17
    
    echo "$a == $b (core comp oper): ", var_dump($a==$b);
    echo "$a == $b (with bc func)  : ", var_dump( bccomp($a, $b)==0 );
    

    결과:

    0.17 == 0.17 (core comp oper): bool(false)
    0.17 == 0.17 (with bc func)  : bool(true)
    
  4. ==============================

    4.전에 말했듯이, PHP에서 부동 소수점 비교 (equal-to, greater-than 또는 less-than)를 수행 할 때는 매우주의해야합니다. 그러나 소수 자리에 관심이있는 경우 다음과 같이 할 수 있습니다.

    전에 말했듯이, PHP에서 부동 소수점 비교 (equal-to, greater-than 또는 less-than)를 수행 할 때는 매우주의해야합니다. 그러나 소수 자리에 관심이있는 경우 다음과 같이 할 수 있습니다.

    $a = round(0.17, 2);
    $b = round(1 - 0.83, 2); //0.17
    if($a == $b ){
        echo 'a and b are same';
    }
    else {
        echo 'a and b are not same';
    }
    

    소수 2 자리 (또는 3 또는 4)로 반올림을 사용하면 예상 한 결과가 나옵니다.

  5. ==============================

    5.네이티브 PHP 비교를 사용하는 것이 좋습니다.

    네이티브 PHP 비교를 사용하는 것이 좋습니다.

    bccomp($a, $b, 3)
    // Third parameter - the optional scale parameter
    // is used to set the number of digits after the decimal place
    // which will be used in the comparison. 
    
  6. ==============================

    6.평등과 비교할 부동 소수점 값이있는 경우 OS, 언어, 프로세서 등의 내부 반올림 전략의 위험을 피하는 간단한 방법은 다음과 같이 값의 문자열 표현을 비교하는 것입니다.

    평등과 비교할 부동 소수점 값이있는 경우 OS, 언어, 프로세서 등의 내부 반올림 전략의 위험을 피하는 간단한 방법은 다음과 같이 값의 문자열 표현을 비교하는 것입니다.

    그렇게하면 평등을 볼 수 있고 PHP 응답은 원하는 것과 같습니다. 값을 읽을 때 평등하다면 예상대로 진술이 true가됩니다.

  7. ==============================

    7.부동 소수점 또는 십진수를 비교하는 솔루션입니다.

    부동 소수점 또는 십진수를 비교하는 솔루션입니다.

    //$fd['someVal'] = 2.9;
    //$i for loop variable steps 0.1
    if((string)$fd['someVal']== (string)$i)
    {
        //Same
    }
    

    10 진수 변수를 문자열로 변환하면 괜찮을 것입니다.

  8. ==============================

    8.이것은 나를 위해 PHP 5.3.27에서 작동합니다.

    이것은 나를 위해 PHP 5.3.27에서 작동합니다.

    $payments_total = 123.45;
    $order_total = 123.45;
    
    if (round($payments_total, 2) != round($order_total, 2)) {
       // they don't match
    }
    
  9. ==============================

    9.수용 할 수있는 소수점 이하의 유한 한 소수점이있는 경우 다음과 같이 작동합니다 (엡실론 솔루션보다 느린 성능 임에도 불구하고).

    수용 할 수있는 소수점 이하의 유한 한 소수점이있는 경우 다음과 같이 작동합니다 (엡실론 솔루션보다 느린 성능 임에도 불구하고).

    $a = 0.17;
    $b = 1 - 0.83; //0.17
    
    if (number_format($a, 3) == number_format($b, 3)) {
        echo 'a and b are same';
    } else {
        echo 'a and b are not same';
    }
    
  10. ==============================

    10.만약 당신이 그것을 쓰면 아마 효과가있을 것입니다. 그래서 당신이 질문을 단순화했다고 상상해보십시오. (질문을 간단하고 간결하게 유지하는 것이 일반적으로 매우 좋은 방법입니다.)

    만약 당신이 그것을 쓰면 아마 효과가있을 것입니다. 그래서 당신이 질문을 단순화했다고 상상해보십시오. (질문을 간단하고 간결하게 유지하는 것이 일반적으로 매우 좋은 방법입니다.)

    그러나이 경우에는 하나의 결과가 계산이고 하나의 결과는 상수라고 상상해보십시오.

    이는 부동 소수점 프로그래밍의 기본 규칙을 위반합니다. 평등 비교는 절대로하지 마십시오.

    이것에 대한 이유는 약간 미묘하지만 기억해야 할 중요한 점은 대개 근본적인 가치를 제외하고는 (역설적이게 제외하고) 일반적으로 작동하지 않는다는 것과 그 대체 방법이 다음의 라인을 따라 퍼지 비교라는 것입니다.

    if abs(a - y) < epsilon
    

    1. 주요 문제 중 하나는 프로그램에 숫자를 쓰는 방식입니다. 우리는 이것을 십진수 문자열로 씁니다. 결과적으로 우리가 작성하는 대부분의 분수에는 정확한 기계 표현이 없습니다. 이진수로 반복하기 때문에 정확한 유한 형식이 없습니다. 모든 기계 분수는 x / 2n 형식의 유리수입니다. 자, 상수는 10 진수이고 모든 십진 상수는 x / (2n * 5m) 형식의 유리수입니다. 5m 숫자는 홀수이므로 어떤 숫자 든 2n 요소가 없습니다. m == 0 일 때만 분수의 2 진수 및 10 진수 확장 모두에 유한 표현이 있습니다. 그래서 1.25는 5 / (22 * 50)이지만 0.1은 1 / (20 * 51)이기 때문에 정확하지 않습니다. 사실 시리즈 1.01 .. 1.99에서 숫자 중 3 개만 정확하게 나타낼 수 있습니다 : 1.25, 1.50, 1.75.

  11. ==============================

    11.평등을위한 수레를 비교하는 것은 순진한 O (n) 알고리즘을 가지고 있습니다.

    평등을위한 수레를 비교하는 것은 순진한 O (n) 알고리즘을 가지고 있습니다.

    각 부동 소수점 값을 문자열로 변환 한 다음 정수 비교 연산자를 사용하여 각 부동 소수점 문자열 표현의 왼쪽에서 시작하는 각 숫자를 비교해야합니다. PHP는 비교하기 전에 각 인덱스 위치의 숫자를 정수로 자동 캐스팅합니다. 첫 번째 숫자가 다른 숫자보다 크면 루프가 중단되고 해당 루프가 속한 float가 더 큰 것으로 선언됩니다. 평균적으로, 1 / 2 * n 비교가있을 것입니다. 서로 같은 수레에 대해 n 개의 비교가 있습니다. 이것은 알고리즘에 대한 최악의 시나리오입니다. 가장 좋은 경우는 각 부동 소수점의 첫 번째 숫자가 다르므로 하나의 비교 만 발생합니다.

    유용한 결과를 얻으려는 의도로 원시 부동 값에 INTEGER COMPARISON OPERATORS를 사용할 수 없습니다. 이러한 연산의 결과는 정수를 비교하지 않기 때문에 의미가 없습니다. 의미없는 결과를 생성하는 각 연산자의 도메인을 위반하고 있습니다. 델타 비교에서도 마찬가지입니다.

    정수 비교 연산자는 정수 비교 연산자를 사용합니다.

    단순화 된 해결책 :

    <?php
    
    function getRand(){
      return ( ((float)mt_rand()) / ((float) mt_getrandmax()) );
     }
    
     $a = 10.0 * getRand();
     $b = 10.0 * getRand();
    
     settype($a,'string');
     settype($b,'string');
    
     for($idx = 0;$idx<strlen($a);$idx++){
      if($a[$idx] > $b[$idx]){
       echo "{$a} is greater than {$b}.<br>";
       break;
      }
      else{
       echo "{$b} is greater than {$a}.<br>";
       break;
      }
     }
    
    ?>
    
  12. ==============================

    12.PHP 7.2의 경우 PHP_FLOAT_EPSILON (http://php.net/manual/en/reserved.constants.php)에서 작업 할 수 있습니다.

    PHP 7.2의 경우 PHP_FLOAT_EPSILON (http://php.net/manual/en/reserved.constants.php)에서 작업 할 수 있습니다.

    if(abs($a-$b) < PHP_FLOAT_EPSILON){
       echo 'a and b are same';
    }
    
  13. ==============================

    13.나는 그것을 말하기 싫지만 "나를 위해 일한다":

    나는 그것을 말하기 싫지만 "나를 위해 일한다":

    Beech:~ adamw$ php -v
    PHP 5.3.1 (cli) (built: Feb 11 2010 02:32:22) 
    Copyright (c) 1997-2009 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
    Beech:~ adamw$ php -f test.php
    a and b are same
    

    부동 소수점 비교는 일반적으로 까다 롭습니다. 동일한 것으로 예상 할 수있는 것은 없습니다 (반올림 오류 및 / 또는 표현 뉘앙스로 인해). http://floating-point-gui.de/를 읽고 싶을 수도 있습니다.

  14. ==============================

    14.

    if( 0.1 + 0.2 == 0.3 ){
     echo 'a and b are same';
    }
    else {
     echo 'a and b are not same';
    }
    

    IEEE 표준 부동 소수점 연산 (이 문제가 있음) 때문에 문제가 발생할 수 있습니다.

  15. ==============================

    15.여기에 하나의 무시 무시한 함정이 ...

    여기에 하나의 무시 무시한 함정이 ...

    서명 된 수레로 작업하는 경우 두 가지 비교를 통해 근접성을 확인하는 것이 좋습니다.

    $a - $b < EPSILON && $b - $a < EPSILON
    
  16. ==============================

    16.

    //You can compare if less or more.
    
    $parcela='250.23'; //total value
    $tax = (double) '15.23'; //tax value
    $taxaPercent=round((100*$tax)/$parcela,2); //tax percent 
    
    $min=(double) '2.50';// minimum tax percent                             
    
    if($taxaPercent < $min ){
        // tax error tax is less than 2.5
    }
    
  17. ==============================

    17.나는 단순히 다음과 같이 끝냈다.

    나는 단순히 다음과 같이 끝냈다.

      uasort($_units[$k], function($a, $b)
                         {
                            $r = 0;
                            if ($a->getFloatVal() > $b->getFloatVal()) $r = 1;
                            if ($a->getFloatVal() < $b->getFloatVal()) $r = -1;
                            //print_r(["comparing {$a->getFloatVal()} vs {$b->getFloatVal()} res {$r}"]);
                            return $r * -1;
                          }
      );    
    
  18. ==============================

    18.

    function floatcmp($f1,$f2,$precision = 10)
    {
        $e = pow(10,$precision);
        return (intval($f1 * $e) == intval($f2 * $e));
    }
    

    테스트 케이스

    $a = 0.17;
    $b = 0.17;
    
    echo floatcmp($a,$b) ? 'yes' : 'no'; // yes
    echo floatcmp($a,$b + 0.01) ? 'yes' : 'no'; // no
    
  19. ==============================

    19.

    function compareFloats($a, $b){
        list($a_int, $a_dec) = explode('.', strval($a));
        list($b_int, $b_dec) = explode('.', strval($b));
    
        if(intval($a_int) == intval($b_int) && intval($a_dec) == intval($b_dec)){
            return 'same';
        }else{
            if((intval($a_int) < intval($b_int)) || (intval($a_int) === intval($b_int) && intval($a_dec) < intval($b_dec))){
                return 'smaller';
            }
            if((intval($a_int) > intval($b_int)) || (intval($a_int) === intval($b_int) && intval($a_dec) > intval($b_dec))){
                return 'bigger';
            }
            return 'error';
        }
    }
    
  20. from https://stackoverflow.com/questions/3148937/compare-floats-in-php by cc-by-sa and MIT license