Why do I get different results for the same values sent to a function in PHP?

0

I need to turn TIME into DECIMAL and then do the opposite operation. I created the functions as shown below, but the result was not efficient because, depending on the origin of the value, the result is different, even though it is the same Type.

Follow the Code:

<?php
// Nutro as variáveis com o mesmo valor e o mesmo tipo de Type
// Mas uma de forma direta e outra via uma function.
$A = 1.01694444444; // Esta dá o retorno errado da function Func_1
$B = Func_2('01:01:01'); // Esta dá o retorno correto da function Func_1

echo $A . '<br />' . $B;

echo "<br /><br />";

// Mas o resultado dos cálculos da function abaixo é diferente
echo Func_1($A) . '<br />' . Func_1($B);

function Func_2($time){
   $hms = explode(":", $time);
   return ($hms[0] + ($hms[1]/60) + ($hms[2]/3600));
}

function Func_1($dec){
   $seconds = ($dec * 3600);
   $hours = floor($dec);
   $seconds -= $hours * 3600;
   $minutes = floor($seconds / 60);
   $seconds -= $minutes * 60;
   return lz($hours).":".lz($minutes).":".lz($seconds);
} 

function lz($num){
   return (strlen($num) < 2) ? "0{$num}" : $num; 
}
?>

I've looked everywhere, but I do not know how to solve it. Here is a LINK from the example above: link

    
asked by anonymous 17.08.2018 / 16:16

2 answers

3

As I already posted in the comments, it is a rounding problem caused by the use of float .

I suggest changing it this way:

function Func_1($dec){
   $seconds = round($dec * 3600); // <---- acrescentado o round
   $hours = floor($dec);
   $seconds -= $hours * 3600;
   $minutes = floor($seconds / 60);
   $seconds -= $minutes * 60;
   return lz($hours).":".lz($minutes).":".lz($seconds);
} 

See working at IDEONE .

Using the rest remainder operator ( % ) and the sprintf formatting function simplify a bit, and eliminate the lz function completely:

function Func_1($dec){
   $s       = round($dec*3600);
   $hours   = floor($dec);
   $minutes = floor(($s%3600)/60);
   $seconds = $s%60;
   return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
} 

function Func_2($time){
   $hms = explode(":", $time);
   return $hms[0] + $hms[1]/60 + $hms[2]/3600;
}

See working at IDEONE .

Here is some theory that can help in understanding:

  

What is the correct way to use float, double, and decimal types?

    
17.08.2018 / 16:47
2

In the function Func_2() method you only treat integers .

In the Func_1() method you are doing calculations with a floating value ( float, double, real ).

A solution option rounds the decimals of the seconds:

$seconds = round($seconds);


function Func_1($dec){
   $seconds = ($dec * 3600);
   $hours = floor($dec);
   $seconds -= $hours * 3600;
   $minutes = floor($seconds / 60);
   $seconds -= $minutes * 60;
   $seconds = round($seconds);
   return lz($hours).":".lz($minutes).":".lz($seconds);
}

Added to $seconds already with all calculations to avoid previous error.

If it does not work, show us the failure to treat!

    
17.08.2018 / 16:40