Use the initial precision when applying factor to a field without digits

Without digits the full representation of the number is used which might not
be the expected behaviour because applying the factor will result in a number
which short representation could be surprising to the user.

Closes #10460
This commit is contained in:
Nicolas Évrard
2025-05-19 11:31:28 +02:00
parent 686c3eff35
commit 2b8f96f8aa
2 changed files with 21 additions and 0 deletions
+11
View File
@@ -2062,12 +2062,23 @@
},
apply_factor: function(record, value, factor) {
if (value !== null) {
// The default precision is the one used by value (before
// applying the factor), per the ecmascript specification
// it's the shortest representation of said value.
// Once the factor is applied the number might become even
// more inexact thus we should rely on the initial
// precision + the effect factor will have
// https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring
let default_precision = (value.toString().split('.')[1] || '').length;
default_precision += Math.ceil(Math.log10(factor));
value /= factor;
var digits = this.digits(record);
if (digits && (digits[1] !== null)) {
// Round to avoid float precision error
// after the division by factor
value = value.toFixed(digits[1]);
} else {
value = value.toFixed(default_precision);
}
value = this.convert(value);
}
@@ -459,10 +459,20 @@ class FloatField(Field):
def apply_factor(self, record, value, factor):
if value is not None:
# The default precision is the one used by value (before
# applying the factor), as python uses the shortest representation
# of said value.
# Once the factor is applied the number might become even
# more inexact thus we should rely on the initial
# precision + the effect factor will have
default_precision = len((str(value).split('.', 2) + [''])[1])
default_precision += math.ceil(math.log10(factor))
value /= factor
digits = self.digits(record)
if digits:
value = round(value, digits[1])
else:
value = round(value, default_precision)
value = self.convert(value)
return value