Edward Tanguay
Edward Tanguay

Reputation: 193352

Why can this usort() function not properly sort decimals?

Why are decimals not properly sorted:

13
11
14
10
12.5
---------------------------------------------------------
descending order:
14
12.5
13
11
10

with this code:

class Customer {
    public $score;
    public function __construct($score) {
        $this->score = $score;
    }
}

$customers = [];
$customers[] = new Customer(13);
$customers[] = new Customer(11);
$customers[] = new Customer(14);
$customers[] = new Customer(10);
$customers[] = new Customer(12.5);

if(is_array($customers) && count($customers) > 0)
{
    foreach($customers as $customer)
    {
        echo '<div>'.$customer->score.'</div>';
    }
}

echo '<hr/>';
echo '<div>descending order:</div>';
usort($customers, function($a, $b) {
    return $b->score - $a->score;
});


if(is_array($customers) && count($customers) > 0)
{
    foreach($customers as $customer)
    {
        echo '<div>'.$customer->score.'</div>';
    }
}

Upvotes: 5

Views: 1063

Answers (3)

Sreepal
Sreepal

Reputation: 59

usort($customers, function($a, $b) {
    return (int)$b->score - (int)$a->score;
});

For example your input is 14.9,14 and 14.5 and the output as 14.9,14 and 14.5, it's treated as, 14.9=14,14.0=14 and 14.5=14

Upvotes: -1

n-dru
n-dru

Reputation: 9430

Casting decimal 0.5 to integer changes it to 0. Change your usort function to:

usort($customers, function($a, $b) {
    if($b->score - $a->score >= 0){
        return 1;
    }
    return -1;
});

Output:

descending order:
14
13
12.5
11
10

PHP Manual says:

Caution: Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.

Upvotes: 5

hvtruong
hvtruong

Reputation: 170

try

usort($customers, function($a, $b) {
    return strnatcmp($b->score,$a->score);
});

Upvotes: 2

Related Questions