Re: [csswg-drafts] [css-values-5] Make UA, not author, deal with floating point errors in random() (#11864)

The CSS Working Group just discussed `[css-values-5] Make UA, not author, deal with floating point errors in random()`, and agreed to the following:

* `RESOLVED: accept the epsilon proposal, with follow-up refinements as needed`

<details><summary>The full IRC log of that discussion</summary>
&lt;emilio> TabAtkins: `random()` has been getting some attention. gets a numeric range, with an optional step<br>
&lt;emilio> ... if you have 100, 200, 150 ... [missing]<br>
&lt;emilio> ... works fine with integer values, but not with floating points<br>
&lt;emilio> ... because 0.1 * 3 is one step further than 0.3<br>
&lt;emilio> ... exact details about the number system would expose this sort of precision issues unpredictably<br>
&lt;emilio> ... even where these are consistent people get bit by this all the time<br>
&lt;emilio> ... floating point math is hard<br>
&lt;emilio> ... various ways to get around<br>
&lt;emilio> ... an epsilon<br>
&lt;emilio> ... that's what we proposed adding<br>
&lt;emilio> ... whenever you calculate the steps you calculate an epsilon of 1/1000th of the step size<br>
&lt;emilio> ... as long as that's around the max we include it<br>
&lt;emilio> ... 1/1000 is more than large enough for any precision issues but small enough to not triggering it accidentally<br>
&lt;emilio> ... authors might need to spell out 1.3333 to get reliably<br>
&lt;iank_> When you get to the extreme values doesn't floating-point go outside the 1% range?<br>
&lt;emilio> ... unless any objections that's on the spec already<br>
&lt;emilio> +1<br>
&lt;weinig> q+<br>
&lt;emilio> q+<br>
&lt;emilio> s/+1//<br>
&lt;emilio> iank_: only when you get to extraordinarily extreme values<br>
&lt;emilio> ... not reasonable to be used in CSS<br>
&lt;kbabbitt> s/iank_:/TabAtkins:/<br>
&lt;iank_> ok<br>
&lt;emilio> ... if you get beaten by it you're going to have problems anyways<br>
&lt;astearns> ack weinig<br>
&lt;emilio> ... even for 1M pixels you should be fine<br>
&lt;emilio> weinig: if the only use case is evenly dividing ranges by a number<br>
&lt;emilio> ... an alternative would be to have a keyword that specifies that instead of a step size you specify the number of buckets<br>
&lt;emilio> ... the impl then can do it for any value<br>
&lt;emilio> ... barring that there's also a more classical, similar function from TAOCP, using the ...<br>
&lt;emilio> ... from "accuracy of floating point arithmetic" from TAOCP<br>
&lt;emilio> ... I'll paste it in<br>
&lt;emilio> TabAtkins: certainly happy to defer to people that have thought more about it<br>
&lt;emilio> ... certainly happy to about<br>
&lt;emilio> weinig: the important bit is that the epsilon is not constant<br>
&lt;emilio> TabAtkins: don't want to force people to write a calc() to get the right thing<br>
&lt;emilio> ... so it can also work with 1.3333 or so<br>
&lt;emilio> weinig: I really worry about trying to invent our own thing<br>
&lt;emilio> ... specially if a property has small numbers or ranges far away from zero<br>
&lt;emilio> ... so trying to find another solution seems wise here<br>
&lt;dholbert> q+<br>
&lt;emilio> TabAtkins: re. your first question about dividing the range in buckets, issue is usability<br>
&lt;emilio> ... in the abstract it's the same<br>
&lt;emilio> ... in practice knowing the number of buckets means range / step size<br>
&lt;emilio> ... you have start and end, calculating the number of buckets needs unit division<br>
&lt;emilio> ... inclined to avoid that one even it does solve the fundamental issue<br>
&lt;fantasai> scribe+<br>
&lt;astearns> ack emilio<br>
&lt;fantasai> emilio: Was going to suggest same as weining, can't you get around the unit size with round() ... I guess it gets complicated if you want to handle mixed units<br>
&lt;fantasai> ... but definitely annoying<br>
&lt;fantasai> TabAtkins: the atan() hack for stripping units is not great<br>
&lt;astearns> ack fantasai<br>
&lt;emilio> fantasai: wanted to say that the idea that I have four segments, rather than step by 10px, is a different feature<br>
&lt;emilio> ... but not the same<br>
&lt;emilio> ... we should make the step size work in an intuitive way<br>
&lt;emilio> ... given the step size, if they're 0.1% to the end, it seems we should use the end<br>
&lt;weinig> The floating point comparison accuracy compare function from Knuth is - Knuth, D. E. "Accuracy of Floating Point Arithmetic." The Art of Computer Programming. 3rd ed. Vol. 2. Boston: Addison-Wesley, 1998. 229-45.<br>
&lt;emilio> ... I think making the author deal with this by round() or so is really hostile<br>
&lt;emilio> ... we should be handling that math for them<br>
&lt;emilio> ... only case where we might want to do the accuracy comparison is if you don't have any step size indicated<br>
&lt;emilio> ... so I think tab's proposal is the right way to go<br>
&lt;kizu> +1 to the proposal as well<br>
&lt;astearns> ack dholbert<br>
&lt;emilio> ... trying to just solve the floating point case is not a good idea<br>
&lt;weinig> (boost has a good write up, https://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html)<br>
&lt;emilio> dholbert: regarding the 3.333 from 0 to 10, thinking about 6.66667 from 0 to 20<br>
&lt;emilio> ... seems this would introduce an arbitrary minimum amount of precision<br>
&lt;emilio> ... to get the right result<br>
&lt;emilio> ... maybe seems slightly surprising that it automatically starts rounding at a particular rounding of precision<br>
&lt;emilio> ... feels a bit magical<br>
&lt;emilio> TabAtkins: you're right that you need at least 4 digits<br>
&lt;emilio> dholbert: maybe unavoidable<br>
&lt;emilio> TabAtkins: yeah, spec says to provide five digits of precision intentionally<br>
&lt;emilio> astearns: sounds like the proposed resolution is to accept the epsilon proposal subject to some refinement looking through the literature<br>
&lt;emilio> ... is that good enough?<br>
&lt;emilio> weinig: don't wanna block it, this seems like a good start<br>
&lt;emilio> fantasai: I think the "let's split into n parts" is not bad<br>
&lt;emilio> ... it's just a different feature<br>
&lt;emilio> weinig: some wording for pixels vs numbers having different epsilons could be good to think about<br>
&lt;emilio> TabAtkins: I think you're right that a unit-based approach might be useful<br>
&lt;emilio> weinig: the reason why this is on my mind is that we recently had an issue with epsilons in the color space, to determine something if something is powerless<br>
&lt;emilio> ... and that epsilon wasn't defined, and the value in webkit was too large<br>
&lt;emilio> ... getting this right can cause real issues<br>
&lt;emilio> ... I wanna think a bit harder about it for the color part but these are details that we can work out<br>
&lt;emilio> astearns: proposal is to accept the draft with follow-up refinements as needed<br>
&lt;emilio> RESOLVED: accept the epsilon proposal, with follow-up refinements as needed<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11864#issuecomment-2737371942 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 19 March 2025 16:49:50 UTC