Jump to content

Float field & rounding


apeisa
 Share

Recommended Posts

Does it work? It seems to always round with 4 decimals (saving values through api). I have tried set value of "Number of decimal digits to round to" to 2 and 6 and I always end with decimals like: 60.2311, not 60.23 or 60.231148

Link to comment
Share on other sites

I've never tried, just shooting blind, but there is a difference between how many places you round to and how many digits you show – maybe four digits is default length of the part after the comma (I'm not completely sure how do we call it in english :) in formatted output?

A.

Edit: and just in case I'm right and you're outputting the float via simple echo (not sprintf('%.2f')), there might be an bug – no correlation between rounding and number of floating decimals or something.

Link to comment
Share on other sites

The configuration option to set the precision of floats was specific to the Inputfield rather than the Fieldtype. Since the Inputfield is only used interactively (not in the API) the precision wasn't applicable to the API. That doesn't make a lot of sense, and I'm not sure why I set it up that way, but I just changed it. I moved the configuration stuff to the Fieldtype rather than the Inputfield. Now you should be able to set the precision and have it honored by both the API and the admin/inputfield. I think there was also an issue with the precision being ignored in some cases, which has been fixed as well. If you grab the latest commits, it should correct this. Please let me know if it doesn't, or if you run into any other similar issues. Some of these field types don't have many miles on them yet (like the Float one). :)

Thanks,

Ryan

Link to comment
Share on other sites

I can duplicate your result here. I think we must be running up against the bounds of what a default float field in MySQL will support. It looks like 6 digits max, whether before or after the point, from testing here. You could try changing it to a double from PhpMyAdmin, but I usually stick to a normal text field for lat/lng values, or for any longish floating point value that I don't need to use for greater-than/less-than comparisons in selectors. I may update this fieldtype's schema to use a double rather than a float, though I'm not positive even that will support the full scope of lat/lng values. 

  • Like 2
Link to comment
Share on other sites

I changed fields to double and it works nicely.

We actually need them to be floats rather than text since we want easily get queries like: all the events in 60km from this point, please.

Interesting thing when changing to double: 24.9194 => 24.9194049835205. That cannot be real value, since my original data source (last.fm) had those with 6 decimals. Or maybe mysql have some mystical superpowers and internal location database ;)

  • Like 1
Link to comment
Share on other sites

Glad converting to double fixed it. I will update this fieldtype to use double instead. That's interesting how it came up with that number on it's own... I've not used mysql with floating point numbers very much, but it seems like a much more complex subject than I realized before. Good weekend reading material for me :)

Link to comment
Share on other sites

  • 1 year later...

Digging up an old thread, but I wanted to post some more info since the problem still exists. Just like you both confirmed on your own, if I define my decimal places to be rounded out to 6 spots on a float field, it still saves with 4.

I'm saving latitude and longitude values, but I need to be able to use greater-than and less-than comparisons in selectors. Looking at the database via phpMyAdmin, I noticed that the float fieldtype is still being created as a FLOAT column and not DOUBLE. I also noticed that the Length/Values for the column definition of the FLOAT field wasn't defined.

I manually set it to "10,6" (no quotes) and kept it as a FLOAT. It did the trick and the values saved correctly.

HOWEVER - Ryan mentioned the limitation of 6 decimal spots for the FLOAT column type. I did some research it a little and found this info on the MySQL website:

A precision from 0 to 23 results in a four-byte single-precision FLOAT column. A precision from 24 to 53 results in an eight-byte double-precision DOUBLE column.
For maximum portability, code requiring storage of approximate numeric data values should use FLOAT or DOUBLE PRECISION with no specification of precision or number of digits.
Source: http://dev.mysql.com...oint-types.html

Since that's the case, I decided that changing the field type to DOUBLE as apeisa suggested was a better solution and allows for a little more flexibility. Is changing the default column type created for Float fieldtypes from FLOAT to DOUBLE going to be integrated in a future PW release?

Link to comment
Share on other sites

It's been awhile since I looked at this, but I seem to recall some issue with DOUBLE going back into PHP that wasn't an issue with FLOAT, so put it off to research later. I need to take a closer look again. But what you did by modifying the schema directly towards your needs is a fine way to go in this case. ProcessWire is not going to go and change your schema back or anything (unless you change the fieldtype), so it should be safe. But please let me know if you run into any issues with losing precision on the DOUBLE when going to/from PHP.

Link to comment
Share on other sites

  • 5 months later...

I am having some problems with this also, on the dev version. I can't seem to get a float to show a consistent number of decimal places. Some fields seem ok, but others get rounded to no decimal places, even though the full number is stored in the db.

Link to comment
Share on other sites

What are folks wanting to store in these float fields?

If you want to store what would be monetary values then I'd suggest avoiding floats or doubles like the plague. Go with fixed-point values which are usually strings which you manipulate with PHP's bc maths functions. MySQL also supports fixed point numbers using the DECIMAL() type.

Contrary to popular belief, floating point numbers (including doubles) are *extremely* inaccurate number representations. Where floats and doubles shine is where you have to store values from a huge *range*; but they do it at the expense of accuracy. They are almost always inaccurate approximations of the value you want to store.

  • Like 1
Link to comment
Share on other sites

Good point - I guess I initially chose float because decimal and double were not supported. I have often used text fields for numeric values in the past and made use of PHP without problems. I have only rarely used float in the past, but thought they must have been more useful than I thought since since it is the only numeric (other than integer) that is offered in PW.

Anyway, happy to use text, but I still think there is a bug with displaying float decimal places in the admin.

Link to comment
Share on other sites

Thanks for the Flourish suggestion - I did recently see something about it, but hadn't investigated yet - looks like it could come in quite handy.

I know it's been said before, but the community on this forum really is about the best I've ever experienced. I am looking forward to being able to give something back very soon.

  • Like 4
Link to comment
Share on other sites

If you want to store what would be monetary values then I'd suggest avoiding floats or doubles like the plague. Go with fixed-point values which are usually strings which you manipulate with PHP's bc maths functions. MySQL also supports fixed point numbers using the DECIMAL() type.

I once heard that you should use integers for these kind of data, as in instead of $3.256 you'd have 3256 fractions of a cent (and do int calculations with that)

  • Like 1
Link to comment
Share on other sites

That's a good example of fixed-point storage and is certainly one way to address this.

Also, though I'm not 100% sure about this, I seem to remember having heard from accounting circles that you should be storing 2 decimal points beyond the smallest unit of currency, not one. Meaning $3.25 would be represented as 32500 and $3.256 as 32560. If that's right, that would apply no matter if you were using strings or integers behind the scenes.

Link to comment
Share on other sites

That's a good example of fixed-point storage and is certainly one way to address this.

Also, though I'm not 100% sure about this, I seem to remember having heard from accounting circles that you should be storing 2 decimal points beyond the smallest unit of currency, not one. Meaning $3.25 would be represented as 32500 and $3.256 as 32560. If that's right, that would apply no matter if you were using strings or integers behind the scenes.

Yeah, I believe it's the case, I've just thought it doesn't matter to illustrate use of (int) with 'decimal' values :)

Link to comment
Share on other sites

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 confused -- I haven't changed anything here, and the getDatabaseSchema() function for FieldtypeFloat still says this:

public function getDatabaseSchema(Field $field) {
  $schema = parent::getDatabaseSchema($field);
  $schema['data'] = 'float NOT NULL';
  return $schema;
}

Can you clarify what you mean about them being stored as ints in the DB? :) I want to make sure I didn't break something. 

Link to comment
Share on other sites

Hi ryan,

Here's my setup:

1) Created a Float-Field "test_float" – no number entered under Details (rounding)

2) Insert a value in test_float, for example 3.5

3) Save

4) Reload and After saving the page, the value in the field is 4

This is also the value stored in the database, see my screenshot.

The schema of "data" is correctly set to float

post-582-0-04759000-1360496491_thumb.png

Link to comment
Share on other sites

Having hard time debuging where my value gets rounded. The post-request ist okay, but:

- InputfieldFloat::sanitizeValue already receives the rounded one.

- Page::setFieldValue also already receives the rounded one

Cannot dig deeper now, but is this something specific or can anyone confirm this issue?

Cheers

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