Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(number-field, slider): floating point roundoff precision bug #4263

Merged
merged 30 commits into from Apr 30, 2024

Conversation

blunteshwar
Copy link
Contributor

@blunteshwar blunteshwar commented Apr 12, 2024

Description

While calculating the moduloStep in validateInput we were not rounding the value due to which when the value of moduloStep was expected to be 0, it was actually 1.7e-17 and causing the error

Related issue(s)

Motivation and context

This change was required because due to wrong value calculation of moduloStep the value of number-field was also incorrect. Now that we are correctly calculating moduloStep the value of number-field is also correct.

How has this been tested?

  • Test case 1
    1. Go here
    2. Add 0.56 in the input field and check the console.

Screenshots (if appropriate)

Before Fix

Screen.Recording.2024-04-12.at.1.11.31.PM.mov

After Fix

Screen.Recording.2024-04-12.at.1.12.34.PM.mov

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (minor updates related to the tooling or maintenance of the repository, does not impact compiled assets)

Checklist

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • If my change required a change to the documentation, I have updated the documentation in this pull request.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices

Best practices

This repository uses conventional commit syntax for each commit message; note that the GitHub UI does not use this by default so be cautious when accepting suggested changes. Avoid the "Update branch" button on the pull request and opt instead for rebasing your branch against main.

@blunteshwar blunteshwar linked an issue Apr 12, 2024 that may be closed by this pull request
1 task
Copy link

github-actions bot commented Apr 12, 2024

Lighthouse scores

Category Latest (report) Main (report) Branch (report)
Performance 0.98 0.99 0.99
Accessibility 1 1 1
Best Practices 1 1 1
SEO 1 0.92 0.92
PWA 1 1 1
What is this?

Lighthouse scores comparing the documentation site built from the PR ("Branch") to that of the production documentation site ("Latest") and the build currently on main ("Main"). Higher scores are better, but note that the SEO scores on Netlify URLs are artifically constrained to 0.92.

Transfer Size

Category Latest Main Branch
Total 228.472 kB 210.377 kB 🏆 210.631 kB
Scripts 60.16 kB 48.21 kB 🏆 48.372 kB
Stylesheet 35.626 kB 30.373 kB 🏆 30.438 kB
Document 5.974 kB 5.189 kB 🏆 5.193 kB
Font 126.712 kB 126.605 kB 🏆 126.628 kB

Request Count

Category Latest Main Branch
Total 43 🏆 45 45
Scripts 35 🏆 37 37
Stylesheet 5 5 5
Document 1 1 1
Font 2 2 2

Copy link

github-actions bot commented Apr 12, 2024

Tachometer results

Chrome

number-field permalink

basic-test

Version Bytes Avg Time vs remote vs branch
npm latest 521 kB 65.42ms - 67.10ms - faster ✔
9% - 12%
6.46ms - 8.97ms
branch 510 kB 73.04ms - 74.90ms slower ❌
10% - 14%
6.46ms - 8.97ms
-

slider permalink

test-basic

Version Bytes Avg Time vs remote vs branch
npm latest 478 kB 74.97ms - 77.06ms - faster ✔
1% - 5%
1.02ms - 4.03ms
branch 466 kB 77.46ms - 79.63ms slower ❌
1% - 5%
1.02ms - 4.03ms
-
Firefox

number-field permalink

basic-test

Version Bytes Avg Time vs remote vs branch
npm latest 521 kB 148.40ms - 154.72ms - faster ✔
4% - 9%
5.93ms - 14.95ms
branch 510 kB 158.78ms - 165.22ms slower ❌
4% - 10%
5.93ms - 14.95ms
-

slider permalink

test-basic

Version Bytes Avg Time vs remote vs branch
npm latest 478 kB 156.92ms - 164.00ms - unsure 🔍
-5% - +0%
-7.88ms - +0.84ms
branch 466 kB 161.44ms - 166.52ms unsure 🔍
-1% - +5%
-0.84ms - +7.88ms
-

@blunteshwar blunteshwar marked this pull request as ready for review April 12, 2024 07:52
@Rajdeepc Rajdeepc changed the title fix(number-field): fixed precision bug fix(number-field): floating point roundoff precision bug Apr 12, 2024
@Rajdeepc Rajdeepc changed the title fix(number-field): floating point roundoff precision bug fix(number-field, slider): floating point roundoff precision bug Apr 12, 2024
Co-authored-by: Rajdeep Chandra <rajrock38@gmail.com>
Rajdeepc
Rajdeepc previously approved these changes Apr 15, 2024
@Westbrook
Copy link
Collaborator

image

I still see the bug outlined in the issue.

We likely need to leverage formatOptions and possibly https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#maximumfractiondigits in some way to step around the expected floating point number issues of working JS.

@Rajdeepc Rajdeepc dismissed their stale review April 24, 2024 16:23

Dismissing Approval due to discrepency in how it is printing in Storybook events

@@ -495,7 +495,14 @@ export class NumberField extends TextfieldBase {
// Step shouldn't validate when 0...
if (this.step) {
const min = typeof this.min !== 'undefined' ? this.min : 0;
const moduloStep = (value - min) % this.step;
this.digitsAfterDecimal =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we cauterize this work to change.get('step') in one of the lifecycle callbacks? I'm not super excited about the this._lastDigitsAfterDecimal !== this.digitsAfterDecimal check, can we leverage the existing cache management mechanics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

@@ -510,6 +512,7 @@ export class NumberField extends TextfieldBase {
value -= this.step;
}
}
value = parseFloat(this.valueFormatter.format(value));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to only format at the end to reduce the chances of fidelity loss?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, We need this const moduloStep = parseFloat(this.valueFormatter.format((value - min) % this.step)); format because in some cases moduloStep is evaluated as 0.00000000000017 or very close to zero , but it should be evaluated to 0, hence this formatting is required.
And we need this value = parseFloat(this.valueFormatter.format(value)); because after modulostep is evaluated the value of step is added to value and hence we again have to finally format it.
Basically the first format is to correctly calculate the moduloStep and the second format is to correctly calculate the value upto required decimal places in accordance with step.

private _numberFormatter?: NumberFormatter;
private _numberFormatterFocused?: NumberFormatter;
private _valueFormatter!: NumberFormatter;
private digitsAfterDecimal: number = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to keep this on the class, or can we use cache clearing to trigger the use of valueFormatter as a getter and contain this value therein?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can totally do that

Comment on lines 708 to 715
const digitsAfterDecimal =
this.step != Math.floor(this.step)
? this.step.toString().split('.')[1].length
: 0;
this._valueFormatter = new NumberFormatter(
this.languageResolver.language,
{ maximumFractionDigits: digitsAfterDecimal }
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need to populate the cache here, if we evict it, the use of this.valueFormatter later will automatically populate it on demand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@blunteshwar blunteshwar requested review from Westbrook and removed request for Westbrook April 30, 2024 03:02
Copy link
Collaborator

@Westbrook Westbrook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working through this. LGTM!

@Westbrook Westbrook merged commit 74480ef into main Apr 30, 2024
49 checks passed
@Westbrook Westbrook deleted the blunteshwar/slider-not-rounding-values branch April 30, 2024 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Editable Slider not rounding values
3 participants