Jump to content

Float field rounding problem


Luis
 Share

Recommended Posts

Hi,

got a little problem with a float field. 

Precision is set to 2. 

If i input numbers > 10 000 the field rounds to 0 decimals. 

e.g. i set the field to 10000.95 it saves 10001

Rounding numbers smaller than 10000 works perfect, so 9999.91 is saved as 9999.91

any ideas?

Link to comment
Share on other sites

Hi Luis,

weird thing! I have tested a bit with PW Version 2.3 stable, and it seems that PW and PHP also does a right job. But MySQL could be wrong.

I have created a float field and it works as you have described, but also when trying to save 10000.11 it store and retrieve 10000.1 !!

But to be short, I have tracked the action until to PW saves the value:

"INSERT INTO `field_test_float` (pages_id, data) VALUES('1109', '10000.11') ON DUPLICATE KEY UPDATE data=VALUES(data)"

After that, I have looked into that field with a MySQL-Editor and it stores 10000,1 and not 10000,11 (When you use 10000,16, it will result into 10000,2)

So, after that I have manually edited the field in the MySQL-Editor, typed 10000,11, save, refresh, and voila there are only 10000,1 in it !

It's definitely a MySQL-thing. But I haven't found a solution, only some posts on stackoverflow and mysql datasheets that I do not understand :)

http://stackoverflow.com/questions/4520620/float-precision-problem-in-mysql

http://stackoverflow.com/questions/2160810/mysql-whats-the-difference-between-float-and-double

http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

  • Like 3
Link to comment
Share on other sites

  • 4 months later...

I encountered an issue trying to import a table that has float values that were being rounded to integers using the ImportPagesCSV module. The csv table has a latitude and longitude column which I was attempting to import into separate float fields in ProcessWire. The 'number of decimal digits to round to' had been left to the default value of '2' for both of these. When I imported my table, however, the numbers got rounded to the nearest whole number.

I then tried changing the decimal places to '4' for the latitude field and re-importing, and that appeared to work correctly (numbers for that field retained four digits after the decimal). I then reset that parameter in the field type back to '2' and re-ran the import, and again it appeared to work correctly, rounding to 2 decimal places instead of 0. The longitude field, which I left alone, always rounded to the nearest whole number.

It would seem that the float types aren't seeing the 'default' decimal digits of '2' but instead are using a value of '0' (or null?) unless it is manually set.

Digging around in the code a bit, does it make sense that this section of InputfieldFloat.module...

        public function __construct() {
                $this->set('precision', 2);
                parent::__construct();
        }

        public function init() {
                parent::init();
                $this->attr('step', 'any'); // HTML5 attr required to support decimals with 'number' types
        }

...should be replaced with...

        public function init() {
                parent::init();
                $this->attr('step', 'any'); // HTML5 attr required to support decimals with 'number' types
                $this->attr('precision', 2);  
      }

Still trying to get my bearings with ProcessWire, so any general insights would be much appreciated.

Link to comment
Share on other sites

In this case, I'm not sure that it would matter whether precision was set in construct or init. They will both be called before a sanitizeValue(), render() or processInput. Are you seeing a different behavior by moving it? Also, for lat/lng coordinates, I recommend setting the precision to 6. If you don't need to make calculations on the values in queries, then I'd just use a text field (rather than float field) to store your coordinates. You might also want to look at the FieldtypeMapMarker module, which bundles in all the map data into an easy-to-use field. Though not sure you could import to that with ImportPagesCSV, though API imports to it are an easy matter. 

Link to comment
Share on other sites

In this case, I'm not sure that it would matter whether precision was set in construct or init. They will both be called before a sanitizeValue(), render() or processInput. Are you seeing a different behavior by moving it? Also, for lat/lng coordinates, I recommend setting the precision to 6. If you don't need to make calculations on the values in queries, then I'd just use a text field (rather than float field) to store your coordinates. You might also want to look at the FieldtypeMapMarker module, which bundles in all the map data into an easy-to-use field. Though not sure you could import to that with ImportPagesCSV, though API imports to it are an easy matter. 

Ryan, thank you for the tips. Unfortunately, I haven't taken the time to experiment any further to try to isolate the issue. I had looked into the MapMarker module, but need to use the lat/lot with Form Builder, which doesn't accept that field type (or at least didn't appear to when I initially set up the form). It appears I have a workable solution for now by manually resetting the precision, but if I can get a few other items checked off my list, I'll try to revisit it in more detail and let you know if I find anything of note.

Link to comment
Share on other sites

After having a problem with floats, we found out that all the PHP float and number function aren't locale save and compatible.

We have a language support installed and the german locale is set via the language pack, after that the float fields stop working correctly. After removing the locale they work again.

It's simply that the locale puts the float like "9,13" and not "9.13" and it fails. It would require some more workarounds as there is now to make it work or just leave out the locale setting when using languages, which is kinda annoying not able to use it.

  • Like 2
Link to comment
Share on other sites

  • 2 months later...

After having a problem with floats, we found out that all the PHP float and number function aren't locale save and compatible.

We have a language support installed and the german locale is set via the language pack, after that the float fields stop working correctly. After removing the locale they work again.

It's simply that the locale puts the float like "9,13" and not "9.13" and it fails. It would require some more workarounds as there is now to make it work or just leave out the locale setting when using languages, which is kinda annoying not able to use it.

Any news about this issue? Guess I just stumbled over this problem, because FieltypeFloat worked fine in one installation and now it cuts everything after the decimal.

Link to comment
Share on other sites

Any news about this issue? Guess I just stumbled over this problem, because FieltypeFloat worked fine in one installation and now it cuts everything after the decimal.

What version of PW are you using? I thought we had this fixed on dev quite awhile ago (now 2.4). 

  • Like 1
Link to comment
Share on other sites

Ryan, I just upgraded to 2.4.0 and was able to duplicate the issue. A couple of clues from watching the MySQL tables:

1. When I added a new field of type 'float', it shows up in the 'fields' table but with the 'data' value empty.

2. If I immediately try to use that field in a page (without adjusting the precision, etc.) the saved values round/truncate (didn't test enough to know which) to an integer (I'm using the term loosely... there's no decimal point or trailing digits in the stored value).

3. If I then go back to the field settings > Details and just click 'Save' (the precision reads '2' by default --- I didn't change it), the MySQL 'data' column in the 'fields' table now reads, {"precision":2,"inputType":"text"}

4. If I then go back to the page I had previously edited and enter in a float value, it now properly saves to 2 decimal places.

It appears the precision isn't getting properly stored in the 'fields' table on creation of the field, and that ProcessWire is defaulting to a precision of 0 in the absence of that information. Subsequent changes to the field settings cause that parameter to be set, and things work as expected.

  • Like 1
Link to comment
Share on other sites

It appears the precision isn't getting properly stored in the 'fields' table on creation of the field, and that ProcessWire is defaulting to a precision of 0 in the absence of that information.

Most fields require you to save their settings before they are committed. But the defaults should usually represent the unsaved state. In this case, we should probably make the default precision 0 since that's what it would be if the field hadn't yet been saved. Either that, or we should just not support a 0 precision (as there's probably no point in it for a float) and assume that to be some other default value like 2. I'll try to duplicate here, and if I can I'll adjust this behavior. Thanks for reporting it. 

Link to comment
Share on other sites

  • 6 months later...

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...