I wrote this post at qiita.com. I thought I'll share my epic fail here as well.
Another epic fail I made.
This is a story of me getting mocked by floating point numbers by not reading the document thoroughly. How many times do I have to stress that I should read the docs carefully?!!!??
If you know very well about floating point numbers, you can either skip this post or mock my total idiocy. If you don't know what I'm talking about, this post might help you in the future.
But this is not the 0.1 + 0.2 != 0.3
problem.
Problematic Temperature
I was making a web app where I had to embed some weather forecast using OpenWeatherMap.
API for OWM has tons of info, most of which I don't need. I had to make an array containing what I needed. Hopefully, somebody made a wrapper called OpenWeatherMap-PHP-API.
And some values returned by APIs turned out to be problematic. Below are the samples of data they return.
"temp":{
"day":15.2,
"min":10.11,
"max":15.2,
"night":10.11,
"eve":15.04,
"morn":15.2
},
I only need min
and max.
They stand for 'minimum temp' and 'maximum temp' respectively. When PHP reads this JSON, it stores the values as float.
Due to space restrictions, I wanted to show them in integers, so I tried rounding them off.
The round function (float round ( float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] )
) was what I needed. This function will round the values off into integers ...or so I thought.
The fail
What will happen if I round
ed the values above? Let's say we stored the decoded JSON object in $data.
round($data['temp']['max']) // => 15
round($data['temp']['min']) // => 10
Pretty standard, eh?
However, I live in a place where it snows in winter. Let's run this code sometime between Autumn and Winter, or between Winter and Spring.
The JSON I'd get looks like this:
"temp":{
"min":-0.44,
"max":4.15,
},
aaaaaand:
round($data['temp']['max']) // => 4
round($data['temp']['min']) // => -0 <- WTF?
Damnit PHP?
You might have heard about 0.1 + 0.2 != 0.3
in the computer world. The 'glitch' is yet another specification of floating point numbers. 1 That's how they work!
Wait, what did the PHP manual say about the float
function?
float round ( float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] )
float round.
float.
Deal with it m8, it's your epic fail.
How I solved it
Since rounded number initially being negative didn't matter for my use case, I cast the return to int.
(I could've also ditch round
and directly cast them to int.
)
(int)round($data['temp']['min']) // => 0
-
Yet, PHP output the value that looks like an integer which probably confused me. Why is this the case?ย โฉ
Top comments (1)
You are not the only one who has seen PHP output
-0
;).Sounds like a perfect situation to wrong up some unit tests to prevent regression later down the road.
RTFM gets me every time as well.