Skip to content

Commit

Permalink
[css-values-5] Prevent numeric precision from biting authors by accid…
Browse files Browse the repository at this point in the history
…ent. #11864
  • Loading branch information
tabatkins committed Mar 11, 2025
1 parent b3b5798 commit 40e06b0
Showing 1 changed file with 39 additions and 9 deletions.
48 changes: 39 additions & 9 deletions css-values-5/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,12 @@ Generating a Random Numeric Value: the ''random()'' function</h3>
chosen uniformly randomly from the possible values
that result in an in-range value.

To avoid issues with numeric precision,
if the max value is <em>very close</em> to equalling a stepped value
(above or below it),
the max value is used as the final stepped value instead.
See [[#random-evaluation]] for precise details.

<div class=example>
For example, ''random(100px, 300px, 50px)''
can only resolve to ''100px'', ''150px'', ''200px'', ''250px'', or ''300px'';
Expand All @@ -2044,19 +2050,32 @@ Generating a Random Numeric Value: the ''random()'' function</h3>
While the minimum value is always a possible result,
the maximum value isn't always,
if it's not also a multiple of the step from the minimum.
For example, in ''random(100px, 300px, by 30px)'',
the largest possible value it can resolve to is ''280px'',
6 steps from the minimum value.
For example, in ''random(100px, 200px, 30px)'',
the largest possible value it can resolve to is ''190px'',
3 steps from the minimum value.

Numeric precision issues can be avoiding by using exact formula.

This comment has been minimized.

Copy link
@Loirooriol

Loirooriol Mar 11, 2025

Contributor

This sounds like it should say "can be avoided" instead of "can be avoiding", but I'm still not sure what the sentence is trying to say.

This comment has been minimized.

Copy link
@tabatkins

tabatkins Mar 11, 2025

Author Member

thanks, fixed, and expanded slightly

For example, in ''random(100px, 200px, 33.3px)'',
the largest possible value is ''199.9px'' (not ''200px''),
and in ''random(100px, 200px, 33.4px)'',
the largest possible value is <strong>''166.8px''</strong>,
because 3 steps from the min would give ''200.1px''
which is outside the allowed range.
But in ''random(100px, 200px, 100px / 3)'',
the largest value is guaranteed to be exactly ''200px''
because 3 steps from the min is
(to within the allowed error)
exactly equal to the max.
</div>

<div class=example>
As explained in the definition of ''round()'',
CSS has no "natural" precision for values,
but the step value can be used to assign one.

For example, ''random(100px, 500px, by 1px)''
For example, ''random(100px, 500px, 1px)''
restricts it to resolving only to whole px values;
''random(1, 10, by 1)''
''random(1, 10, 1)''
is restricted to resolving only to integers;
etc.
</div>
Expand Down Expand Up @@ -2392,10 +2411,21 @@ Evaluating Random Values</h3>

: for a ''random()'' function with |min|, |max|, and |step|
::
* Let |N| be the largest integer such that <code>|min| + |N| * |step|</code>
is less than or equal to |max|, plus 1.
* Let |random int| be <css>round(down, |R| * |N|, 1)</css>.
* Return <code>|min| + |random int| * |step|</code>.
* Let |threshold| be <code>|step| / 1000</code>,
or the smallest representable value in the numeric type being used
if |threshold| would round to zero.
* Let |values| be a list containing all values of the form <code>|min| + |N| * |step|</code>,
where |N| is a non-negative integer
and the result is less than or equal to |max|.

If the largest |N| produces a value that is not within |threshold| of |max|,
but |N|+1 would be within |threshold| of |max|,
include the |N|+1 value as well.
* If the largest value in |values| is within |threshold| of |max|,
replace it with |max|.
* Let |length| be the length of |values|.
* Let |random int| be <css>round(down, |R| * |length|, 1)</css>.
* Return the |random int|'th item of |values| (0-indexed).

: for a ''random-item()'' function with |N| <<declaration-value>>? arguments:
::
Expand Down

0 comments on commit 40e06b0

Please sign in to comment.