Jump to content

Float field & rounding


apeisa
 Share

Recommended Posts

Hi ryan,

I could not reprocude this problem on another installation.

Everything works fine on the server of my hosting, first on a 2.2.2 installation then also on 2.2.13.

One thing i noticed: If there's no "number of decimal digits to round to" set, the float value get's rounded to an integer, and this is also the value stored in the Database.

Maybe there should be a default value in this field, for example 2?

Empty or zero makes no sense, because no float gets stored.

Link to comment
Share on other sites

  • 1 month later...
  • 2 weeks later...

Just noticed that with the latest dev, floats are stored as integers in the db.

For example: 0.3423 -> 0, 3.5 -> 3

I'm using text-fields and cast them in PHP to (float) or (double) when needed.

I've noticed that my installation has the same problem. It seems that it has something to do with the language the user has activated. Normally, I use "german" for my main language. In this case the floats are saved integers, no matter if I put 0,35 or 0.35 in the field. If I switch to english, it works. Is there anything I can configure for german?

Link to comment
Share on other sites

I've noticed that my installation has the same problem. It seems that it has something to do with the language the user has activated. Normally, I use "german" for my main language. In this case the floats are saved integers, no matter if I put 0,35 or 0.35 in the field. If I switch to english, it works. Is there anything I can configure for german?

There seems to be a bug: I've just noticed that I can't even use explicit php (float) type casting or floatval() in my template code - it delivers "," as decimal point, not ".", if I'm using german as default language.

Workaround: in line 144 of /wire/modules/LanguageSupport/LanguageSupport.module it says:

$locale = $this->_('0'); // Value to pass to PHP's setlocale(LC_ALL, 'value') function when initializing this language // Default is 'C'. Specify '0' to skip the setlocale() call (and carry on system default).
if($locale != '0') setlocale(LC_ALL, $locale); 

If it is set to $locale = $this->_('0') floats are working as expected. Don't know if this has other side effects though.

How can I made this change "upgrade-save"? Copying the whole module to /site/ gives an error about dependencies.

Ryan, what about changing this module to be configurable?

Link to comment
Share on other sites

There seems to be a bug: I've just noticed that I can't even use explicit php (float) type casting or floatval() in my template code - it delivers "," as decimal point, not ".", if I'm using german as default language.

Workaround: in line 144 of /wire/modules/LanguageSupport/LanguageSupport.module it says:

$locale = $this->_('0'); // Value to pass to PHP's setlocale(LC_ALL, 'value') function when initializing this language // Default is 'C'. Specify '0' to skip the setlocale() call (and carry on system default).
if($locale != '0') setlocale(LC_ALL, $locale); 

If it is set to $locale = $this->_('0') floats are working as expected. Don't know if this has other side effects though.

How can I made this change "upgrade-save"? Copying the whole module to /site/ gives an error about dependencies.

Ryan, what about changing this module to be configurable?

Since I don't need float-types that often, I found a better solution for me. If I'm using float(), I set

setLocale(LC_NUMERIC, 'C');

in the affected template a line before. The file LanguageSupport.module does not need to be changed then.

Link to comment
Share on other sites

That particular setting is meant to be translated per language. If you add /wire/modules/LanguageSupport.module to your translatable files list in Setup > Languages > [language] > then you can adjust the setLocale setting as you see fit, without having to modify the LanguageSupport.module file. Basically, anything that appears in __('') or $this->_('') or $this->_n('') or $this->_x('') is translatable. 

  • Like 1
Link to comment
Share on other sites

  • 4 months later...

With setlocale setted to default values float works:

(2 decimal digits)

#from db
5.69 -> view in admin page as 5.69
#new
5.6899 -> 5.69
5.6 -> 5.6
...

If I change setlocale from Setup->Lanuages->... to it_IT

#from db
5.69 -> view in admin page as 5,69 # so It works, replace . with ,
#new
5,6899 -> 5
5,6 -> 5
5,9999 -> 5
5.69 -> 5
5.9999 -> 6 #!!!!
...

So, in input I can't use , and decimal digits aren't respected.

Thanks

Link to comment
Share on other sites

After some tests.. refer to ___sleepValue in FieldtypeFloat.module

LC_ALL = it_IT


write 2.3 (just for test)

2,2 passed
2.2 after mon_decimal_replace 
2,2 after floatval()

saved as 2.. floatval() use my locale.

write 2,3

2 passed
2 after floatval()

$value is cleared somewhere before this call..

Italian user have to use . (dot), less floatval(). It is wrong.

Link to comment
Share on other sites

I don't think it's related to field dependencies. Sounds like that floatval() at the end needs to come out, but somehow we need to get the value converted to a real float/decimal number that MySQL will accept. You could try commenting out the floatval() at the end of the sleepValue() function in /wire/modules/Inputfield/FieldtypeFloat.module. Maybe we can just pass it to the DB as a string? i'm reluctant to do that since wakeupValue is meant to return a value in it's native state, but if it fixes this issue it'd be worth it. 

Thanks for your testing with this btw. 

Link to comment
Share on other sites

Thanks Ryan.

Also tried commenting out floatval(), it works but:

- IT user must use . (dot) and not , (comma) for decimal separator

- thousands are not respected (1.200,10 -> 1,20 / 1,200.10 -> 1)

$value is edited before floatval() call in sleepValue(). But.. Where? Javascript?

In my examples "XX passed" is the $value echoed at the beginning of sleepValue() function (2,3 -> 2 / 2.3 -> 2,3).

Link to comment
Share on other sites

$value is edited before floatval() call in sleepValue(). But.. Where? Javascript?

Not in javascript. Taking a closer look, both FieldtypeFloat::sanitizeValue() and InputfieldFloat::sanitizeValue() get their hands on the value before sleepValue() does. They just do simple typecasting with (float) and a round() calls. The only thing I can think of is that maybe PHP's round() is not respecting the float internationalization? You might try removing the round() call from both of those functions. When it comes to float i18n it seems like PHP is trying to do too much for us in some places and not enough in others. I find it pretty confusing. :)

Link to comment
Share on other sites

Yes, I confirm that the problem is generated by round(), floatval() and (float).

Float values are vulnerable to rounding errors are they have limited precision. PHP (locale ) and MySQL issue.

In my case I use it for currency (only to store prices, no other operations), so.. How do we store currency in PW? A new FieldTypeDecimal or similar with DECIMAL type in MySQL?

Link to comment
Share on other sites

I just ran into the same problem with float (apeisa shop). It worked well until I added the german language pack!

Now it breaks it, and in german the decimal point it a comma. The locale in the translation is set to de_DE.UTF-8. Removing it works again but then the locale is lost?

What is the problem really? How can we deal with this reliably?

It just that the setlocale where it has comma instead of point the round, floatval float operation fails.

I can for now just disable the setlocale for german, but would be nice if not.

Link to comment
Share on other sites

  • 11 months later...
  • 4 years later...

Would it be possible to set up a number spinner with the float? I can see plenty of situations where that would be helpful. It is not too far off the mark, either, for we already have to set the precision for a "float" (actually a fixed-point number). Suppose I set a precision value k. Then the default value of the spinner step would be 10^-k. However, it could be changed to any number with the precision k. So, for example, I could have a float with the precision 2 and the spinner step set to 0.25. In my experience, while education and leave hours are reported as decimals, they are doled out only in quarter- or half-hours. Thank you!

 

Link to comment
Share on other sites

2 minutes ago, stuartsa said:

Would it be possible to set up a number spinner with the float? I can see plenty of situations where that would be helpful. It is not too far off the mark, either, for we already have to set the precision for a "float" (actually a fixed-point number). Suppose I set a precision value k. Then the default value of the spinner step would be 10^-k. However, it could be changed to any number with the precision k. So, for example, I could have a float with the precision 2 and the spinner step set to 0.25. In my experience, while education and leave hours are reported as decimals, they are doled out only in quarter- or half-hours. Thank you!

 

Please note that I intend to post this on the other thread, which I see now. However, our current forum software does NOT allow deletion of replies.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...