From what I can see, the iPhone timer app is rounding to the nearest second. For positive numbers that can be accomplished with either Math.round(t) or Math.floor(t+0.5).
> Milliseconds are converted to seconds by dividing by 1000 and rounding down like so
It seems like the simpler explanation is that the iPhone actually rounds to the closest integer rather than rounding down. (Whether they do this invisibly by adding 0.5s and rounding down is an implementation detail.)
I realize that. It seems like the entire blog post could be summarized as "I thought about doing something this way and when it didn't give me what I and everyone else expects out of a timer, my mental model adjusted to conclude that Apple was doing some weird gymnastics involving adding 500ms to some of their timer code and using Math.floor() but not to the time the timer actually goes off rather than adjusting my mental model to match the simpler way that humans expect rounding to work in a timer using [the equivalent of] Math.round()."
Agreed, to my eyes it seems clear that the display shows both “5” and “0” for half a second, which means the total duration is still 5 seconds, not 5.5 seconds.
Only at 0:00. That's a separate feature, showing 0:01 at a minimum for a paused timer (presumably to make it very clear that you aren't looking at an expired timer, even though the UI disappears for an expired timer.)
Exactly. Seems like the author is suggesting a timer with 4.9 seconds left should tell you it has 4 seconds left instead of 5. Not sure why anyone would think this.
The tidbit about it displaying 1 even if there is 0.01 left is interesting though. Makes sense.
reddit works like this if you get downvoted and only get to post every 10 minutes. it tells you you have to wait 1 more minute, and then a minute later it tells you you have to wait 59 more seconds, very counterintuitive. gets me every time when I have a post typed out and it's putting me on timeout for going against the grain (like e.g. suggesting that mob justice is bad)
iOS 9 and below, IIRC, the timer app stopwatch screen would really flake out after 1000 hours. By 'flake out' I mean it would slow down the updating a lot - screen got somewhat jerky and slow to respond.
From iOS 10 onwards, 1000+ hours doesn't seem to phase it at all - no slow downs.
source: 1490:43:24 ago I started my timer, but I can't remember why now.
Round half up is a reasonable thing to do with many data types, but it's not something that's typically done with time. Any sensible time handling solution will truncate instead of rounding.
Which is not to call apple's timer nonsensical. I agree with the author that it's a nicer experience, but I think it's likely an intentional decision to make the display look better, not a consequence of naive rounding.
> Any sensible time handling solution will truncate instead of rounding.
That doesn't really work for a countdown timer though since the last second would then display as zero, which is nonsense for 'time remaining'. You have to round up, always.
The Android 9 countdown works intuitively, it takes a second to decrement from 5 to 4 and sounds the alarm exactly at 0. You can't pause it at zero...
> Which is not to call apple's timer nonsensical.
It pretty much is, since the last 'second' takes more than a second to elapse.
But this highlights the difference between the two devices, stopwatches and timers.
A stopwatch counts up. Therefore, it makes sense to use the floor (4.99 is still "4", not yet "5").
A timer counts down. Therefore, it makes sense to use the ceiling (3.01 is still "4", not yet "3").
In fact this was a turning point in the original article: "rounding down . . . makes a lot of sense when counting up. . . . But for a countdown timer, this is counterintuitive."
Yup, that was my motivation for rewriting the parent statement. Abstracting away the type of counter and just saying, "show the number only when you crossed it" basically.
Sorry. First, I thought that you set out to contradict, rather than agree with, the person you replied to (since that is common). Then I was thrown off by your topic sentence, which seemed to lump together the two devices ("timers and stopwatches"). At this point, I think my reading accelerated to highway speeds and totally botched parsing the rest ;)
> Any sensible time handling solution will truncate instead of rounding.
It's not a "handling of time" its just a display. And its extremely sensible to round to the nearest displayable number instead of rounding up or down, because this minimizes the error in the displayed number. And that's what you are interested in, conveying as accurately as possible what the current time is.
Again, I'm not trying to suggest anybody made a wrong choice here, just that they made an intentional decision.
Theres no way this is happening because somebody called math.round() without thinking, you don't round time and the developers who make apple's clock app know that. They made a conscious decision to have the timer work this way. You can disagree with whether they made the right choice, but I'm pretty sure they thought about it.
Conceptually you are attempting to display something that has more precision than you are willing to display.
You can
- Round (Truncation is a type of rounding, Rounding towards zero)
- Adjust the display to increase the precision it displays
- Do both by dynamically increasing the precision of the display/decreasing rounding as the distance to zero closes in.
I think my Garmin smartwatch shows distance rounded up, but plays alerts based on the actual value. So you can have run a watch that says you've run 10.00 km on the display... but have to go a bit further to trigger the 10 km vibration alarm. And crucially if you stopped before the alarm it wouldn't register as a 10 km for your records!
One of the main benefits is that it doesn’t require the internet and can synchronize iPhones, iPads, and Apple TV’s using either peer-to-peer WiFi or Bluetooth with no manual pairing.
Also had an interval timer for exercises, group activities, etc...
I think I find the ceiling method most intuitive. I have noticed that video games with cooldowns tend to agree with me; some ability has a 4 second cooldown, you press it, and the UI says "4", even though 3.999 seconds remain until the ability is back. (This means that you never see "0"; the counter reads "1" for the last second before the cooldown is available again.)
The ceiling method matches with the expectation of how much time is left when the major digit changes, which is the same as how we do countdowns verbally in English.
We say, "5, 4, 3, 2, 1, 0", not "4, 3, 2, 1, 0, done".
This gives me a nostalgic reminder of when I used to watch Nickelodeon GUTS. Whenever a countdown timed challenge was about to end, I would hear the audience count down starting with "10" at maybe 10.7 seconds, "9" at 9.7 seconds, etc. Then after "1", there was a small period of awkward silence and murmurs from the audience before the siren blasted.
It's a good example of how measurement of time in terms of human perception differs from the pure mathematical sense, and rounding is a good compromise here (wherever it doesn't display fractional seconds).
I was thinking of the same phenomenon, but at school sporting events when the crowd would count down while watching the time on the scoreboard. The awkward pause between shouts of “zero!” and the actual buzzer.
Maybe the author should look up different modes of rounding. Round-to-nearest is what's the "intuitive" choice Apple made here. It's not "fake time". Srsly..
Besides, instead of truncating, it would even be sensible to do a round-up here, so that you get "5, 4, 3, 2, 1, done!" Non-mathematicians and non-programmers don't want to stare at 0 for a seconds. They likely don't want to stare at a 0 at all. That wouldn't "fake time" either.
It really gets to me that he writes such an article and his self-description is "I'm a Maker and Full Stack Developer who loves working with the Frontend, Vue.js and User Interface Design." Not a great ad for yourself..
Mature adults should be able to take criticism without getting butt-hurt about it. The real world can be mean and nasty and sometimes you need a wake-up call that you're being silly or screwing up.
I have seen a lot of comments on Hacker News that I thought were mean. This isn't one of them.
Rounding is something I learned in elementary school. If someone in elementary school was unfamiliar with rounding, it would be mean to take them to task about it. But this writer is an adult, a professional programmer, and presumes to be a teacher, by taking the time to publish an article about the subject.
In fact, the writer has even less excuse, because he knows about rounding. Twice he mentions "rounding down". So it is all the more baffling that he did not call what Apple was doing, simply, "rounding up". Instead he wrote a multi-paragraph blog post about adding 500 milliseconds of "fake time", then having to duct-tape over that by making the timer say "0" when the timer reached 500 ms.
Suppose a man bills himself as a car salesman, but every question you ask him about the car, he says the wrong thing. He says the car has 3 wheels when it has 4. He says it is red when it is black. He says the engine is in the back when it is in the front. Would it be mean for you to mention his title, by saying something like, "You say you are a car salesman, but you don't know about this car on your lot." It is right to call someone out for being less than what they say they are.
As for random blog posts on the internet, this isn't so surprising. What's surprising is that it wound up on Hacker News with over 100 votes.
Summary: If you start a timer for 60 seconds it should practically not display 60, but should start at 59,...
This is not intuitive so Apple added 500ms to the visualization.
The way I see it, the problem stated by TFA is simply a mismatch between what wants to be represented vs. what is represented.
Dividing the amount of milliseconds left / 1000 is too naive. If you want that the representation "0 seconds" actually matches the instant when there are actually 0 seconds left (i.e., no more time left), you should label these millisecond ranges as follows:
* 5000 to 4001: "5 seconds"
* 4000 to 3001: "4 seconds"
* 3000 to 2001: "3 seconds"
* 2000 to 1001: "2 seconds"
* 1000 to 0001: "1 second"
* 0: "0 seconds" (which usually the user doesn't read if the screen shows something else)
Simple enough?
The thing is, yes the iPhone timer does something in between, in order to show both the initial (5) and the final (0) numbers for a non-instantaneous amount of time, but (IMHO) that's the most confusing choice.
Everyone is saying "rounding, duh" but that a bit unfair IMO
You should show each integer value second for, ideally, one second (in the case with no display for fractional seconds). So the question is: exactly what rage of time to cover? The poster expected that for second N, it would be:
[N,N+1)
But Apple seems to do:
[N-0.5, N+0.5)
I think the Apple behavior makes perfect sense when you are displaying the current time (eg like a watch). It may be a little less obviously correct for the timer case, but still seems fine. I'd bet they implemented it for the time of day case and just re-used it for the timer case.
Well you have 6 numbers and only 5 seconds to show them in. You could show 0 only when the timer has fully completed.
I think either rounding up, or rounding to the closest integer is fine. The authors expectation of always rounding down is the only option I would never expect.
82 comments
[ 3.1 ms ] story [ 125 ms ] threadIt seems like the simpler explanation is that the iPhone actually rounds to the closest integer rather than rounding down. (Whether they do this invisibly by adding 0.5s and rounding down is an implementation detail.)
That’s most likely what it does indeed, much more elegant than keeping track of the extra 500ms.
It's not "fake".
I would much prefer "0 seconds remaining" to mean 0 to 0.5 seconds remaining, than any other possible case. I would find it much easier to parse.
(Alternatively, please show more accuracy for this case, where it's likely relevant)
The tidbit about it displaying 1 even if there is 0.01 left is interesting though. Makes sense.
Oh, so that's why it's telling me to wait... I always wondered that whenever I got into an argument with someone.
From iOS 10 onwards, 1000+ hours doesn't seem to phase it at all - no slow downs.
source: 1490:43:24 ago I started my timer, but I can't remember why now.
Edit: sencha.app for those curious
It isn't displaying a "fake" time, it's rounding.
https://en.wikipedia.org/wiki/Rounding#Round_half_up
Edit: Note, Round Half Up != Round half away from zero but that isn't important for this scenario :D
Which is not to call apple's timer nonsensical. I agree with the author that it's a nicer experience, but I think it's likely an intentional decision to make the display look better, not a consequence of naive rounding.
That doesn't really work for a countdown timer though since the last second would then display as zero, which is nonsense for 'time remaining'. You have to round up, always.
The Android 9 countdown works intuitively, it takes a second to decrement from 5 to 4 and sounds the alarm exactly at 0. You can't pause it at zero...
> Which is not to call apple's timer nonsensical.
It pretty much is, since the last 'second' takes more than a second to elapse.
> Any sensible time handling solution will round off toward the starting value.
So a stopwatch won't display "1" until a full second has elapsed, and will look like this for five seconds: "0...1...2...3...4...5!"
A timer won't display "4" until a full second has elapsed, and will look like this: "5...4...3...2...1...0!"
In the stopwatch case, the display shows "0" for 0.999 s; in the timer case it'll show "1" for 0.999 s.
A stopwatch counts up. Therefore, it makes sense to use the floor (4.99 is still "4", not yet "5").
A timer counts down. Therefore, it makes sense to use the ceiling (3.01 is still "4", not yet "3").
In fact this was a turning point in the original article: "rounding down . . . makes a lot of sense when counting up. . . . But for a countdown timer, this is counterintuitive."
It's not a "handling of time" its just a display. And its extremely sensible to round to the nearest displayable number instead of rounding up or down, because this minimizes the error in the displayed number. And that's what you are interested in, conveying as accurately as possible what the current time is.
Theres no way this is happening because somebody called math.round() without thinking, you don't round time and the developers who make apple's clock app know that. They made a conscious decision to have the timer work this way. You can disagree with whether they made the right choice, but I'm pretty sure they thought about it.
You can
One of the main benefits is that it doesn’t require the internet and can synchronize iPhones, iPads, and Apple TV’s using either peer-to-peer WiFi or Bluetooth with no manual pairing.
Also had an interval timer for exercises, group activities, etc...
We say, "5, 4, 3, 2, 1, 0", not "4, 3, 2, 1, 0, done".
I get the feeling this pun wasn’t intentional, but it’s a good one nonetheless.
It's a good example of how measurement of time in terms of human perception differs from the pure mathematical sense, and rounding is a good compromise here (wherever it doesn't display fractional seconds).
Besides, instead of truncating, it would even be sensible to do a round-up here, so that you get "5, 4, 3, 2, 1, done!" Non-mathematicians and non-programmers don't want to stare at 0 for a seconds. They likely don't want to stare at a 0 at all. That wouldn't "fake time" either.
It really gets to me that he writes such an article and his self-description is "I'm a Maker and Full Stack Developer who loves working with the Frontend, Vue.js and User Interface Design." Not a great ad for yourself..
Isn't that exactly what you did right here?
Rounding is something I learned in elementary school. If someone in elementary school was unfamiliar with rounding, it would be mean to take them to task about it. But this writer is an adult, a professional programmer, and presumes to be a teacher, by taking the time to publish an article about the subject.
In fact, the writer has even less excuse, because he knows about rounding. Twice he mentions "rounding down". So it is all the more baffling that he did not call what Apple was doing, simply, "rounding up". Instead he wrote a multi-paragraph blog post about adding 500 milliseconds of "fake time", then having to duct-tape over that by making the timer say "0" when the timer reached 500 ms.
Suppose a man bills himself as a car salesman, but every question you ask him about the car, he says the wrong thing. He says the car has 3 wheels when it has 4. He says it is red when it is black. He says the engine is in the back when it is in the front. Would it be mean for you to mention his title, by saying something like, "You say you are a car salesman, but you don't know about this car on your lot." It is right to call someone out for being less than what they say they are.
As for random blog posts on the internet, this isn't so surprising. What's surprising is that it wound up on Hacker News with over 100 votes.
Dividing the amount of milliseconds left / 1000 is too naive. If you want that the representation "0 seconds" actually matches the instant when there are actually 0 seconds left (i.e., no more time left), you should label these millisecond ranges as follows:
* 5000 to 4001: "5 seconds"
* 4000 to 3001: "4 seconds"
* 3000 to 2001: "3 seconds"
* 2000 to 1001: "2 seconds"
* 1000 to 0001: "1 second"
* 0: "0 seconds" (which usually the user doesn't read if the screen shows something else)
Simple enough?
The thing is, yes the iPhone timer does something in between, in order to show both the initial (5) and the final (0) numbers for a non-instantaneous amount of time, but (IMHO) that's the most confusing choice.
You should show each integer value second for, ideally, one second (in the case with no display for fractional seconds). So the question is: exactly what rage of time to cover? The poster expected that for second N, it would be:
[N,N+1)
But Apple seems to do:
[N-0.5, N+0.5)
I think the Apple behavior makes perfect sense when you are displaying the current time (eg like a watch). It may be a little less obviously correct for the timer case, but still seems fine. I'd bet they implemented it for the time of day case and just re-used it for the timer case.
I think either rounding up, or rounding to the closest integer is fine. The authors expectation of always rounding down is the only option I would never expect.
"What time is it now?"
vs
"How much time is left?"