symfony-docs icon indicating copy to clipboard operation
symfony-docs copied to clipboard

NumberType does not apply rouding when scale is not defined

Open pacproduct opened this issue 6 months ago • 4 comments

Hi :)

I may be wrong, but documentation (Symfony 5.x) says that NumberType's option rounding_mode defaults to \NumberFormatter::ROUND_HALFUP : https://symfony.com/doc/5.x/reference/forms/types/number.html#rounding-mode

In my project, one of my form's fields is a NumberType, with no rounding_mode nor scale configured:

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'altitude',
                NumberType::class,
                [
                    'label' => 'common.label.altimetric_reference.altitude',
                    'attr' => ['class' => 'altitude-field'],
                    'required' => false,
                    'help' => 'common.help.value_in_m',
                ]
            )
[...]

But because of how \Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer::getNumberFormatter has been implemented, I think the documentation is not accurate:

    protected function getNumberFormatter()
    {
        $formatter = new \NumberFormatter($this->locale ?? \Locale::getDefault(), \NumberFormatter::DECIMAL);

        if (null !== $this->scale) {
            $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->scale);
            $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode);
        }

        $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping);

        return $formatter;
    }

As shown above, the number formatter is not configured with any rounding when no scale is defined (even if one is configured in the form I reckon). Because of that, in our project (with French locale), the effective rounding mode used is \NumberFormatter::ROUND_HALFEVEN (and scale seems to default to 3). Instead of the advertised \NumberFormatter::ROUND_HALFUP.

This gives us an unexpected and weird behavior when users type in numbers like 485,3485, as it gets rounded to 485,348 instead of 485,349.

In all honesty, I'm not sure if this is a documentation issue, a bug in NumberToLocalizedStringTransformer::getNumberFormatter or if I'm missing something?

Thanks for your insights :)

pacproduct avatar Aug 19 '24 11:08 pacproduct