-
Notifications
You must be signed in to change notification settings - Fork 317
fix(float-precision): correct float widget rounding #4291
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
Conversation
…ion errors Signed-off-by: Alexander Piskun <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great at first glance - thanks for tracking that down. I'll give it a bit of a thrashing and see if there's impact elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested the fix and confirmed it resolves the floating-point precision issue. Values like 0.1 and 1.0 now serialize correctly to JSON without the trailing digits (e.g., no more 0.10000000000000002). The mathematical approach using Math.pow(10, -precision)
is cleaner and more accurate than the previous implementation. LGTM 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing process:
- Basic Float Values in KSampler
- Added KSampler node, set denoise to 0.1
- Saveed workflow and checked JSON - was 0.1 not 0.10000000000000002
- Tested other values: 0.5, 0.25, 0.75, 1.0 - Workflow Save/Load Cycle
- Created workflow with multiple float values
- Saved to file
- Reloaded and verified all float values remain exact - StyleModelApply Node Test
- Added StyleModelApply node
- Set strength to exactly 1.0
- Export and verified it saves as 1 or 1.0, not 1.0000000000000002 - Different Precision Settings
- Went to Settings → Comfy → Float Rounding Precision
- Test with precision 1, 2, 3, 4, 5, 6
- Verify rounding works correctly at each level (except with 6, serializes incorrectly after using buttons) - Edge Case Values
- Very small: 0.001, 0.0001- fails at precision 6 => e.g. 0.000010 serializes to 0.000009999999999999999
- Large values: 100.1, 1000.1
- Values that round badly in binary: 0.1, 0.2, 0.3, 0.7 - fails on precision 6 => e.g. 0.1 serializes to 0.09999999999999999
- fails at precision 6 => e.g. 0.000010 serializes to 0.000009999999999999999
- Multiple Node Types
- Tested float widgets in different nodes:- LoRA nodes (model_weight, clip_weight)
Found a separate issue while testing: #4350
It seems there's some new issues e.g. the serialization of 0.09999999999999999 before it was 0.10000000000000003 |
This comment was marked as outdated.
This comment was marked as outdated.
Signed-off-by: Alexander Piskun <[email protected]>
Hope that this fix(use Found another strange situation during testing: when we set version with logging for fast checkfunction onFloatValueChange(this: INumericWidget, v: number) {
const round = this.options.round
const min = this.options.min ?? -Infinity
const max = this.options.max ?? Infinity
if (round) {
const precision =
this.options.precision ?? Math.max(0, -Math.floor(Math.log10(round)))
const adjusted = v / round
const rounded = Math.round(adjusted) * round
const fixedValue = Number(rounded.toFixed(precision))
const clamped = _.clamp(fixedValue, min, max)
console.log('[onFloatValueChange debug]')
console.log('input value =', v)
console.log('round =', round)
console.log('precision =', precision)
console.log('adjusted = v / round =', adjusted)
console.log(
'rounded (intermediate, possibly imprecise) = Math.round(adjusted) * round =',
rounded
)
console.log(
'fixedValue (final corrected value) = Number(rounded.toFixed(precision)) =',
fixedValue
)
console.log('clamped =', clamped)
this.value = clamped
} else {
console.log('[onFloatValueChange debug] no rounding, value =', v)
this.value = v
}
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested again and works well. The unwanting floating-point noise is successfuly removed and all edge cases are handled.
LGTM, nice work!
This PR addresses a long-standing floating-point precision issue that causes float values like
0.1
to be saved incorrectly as0.10000000000000002
in workflows.Closes:
When a float widget's rounding value was calculated, it was using
Math.pow(0.1, precision)
. Since0.1
cannot be perfectly represented in binary, this introduced a tiny error that propagated into the final widget value.The original code tried to mitigate this with a multiplication/division trick, but the error was already present before that trick could be effective.
This PR was not fully tested, I run tests myself only on a few workflows to prove that there is no such error anymore as in the issues.
┆Issue is synchronized with this Notion page by Unito