0

Assume there is a table named somethings with a column value of type float.

The schema is shown below.

# == Schema Information
#
# Table name: somethings
#
# id         :bigint   not null, primary key
# value      :float    not null
# created_at :datetime not null
# updated_at :datetime not null

Then, "update the value of all records in the somethings table to 0.4, then subtract 0.1".

The code is shown below.

Something.update_all("value = 0.4")
Something.update_all("value = value - 0.1")

After this operation, the value columns of the records in the somethings table are all 0.3000000000000000000000004, resulting in a rounding error.

I want to update without rounding errors, but how can I do it?

Note that I am aware that if I write the following without update_all, there will be no rounding error.

Something.update_all("value = 0.4")

Something.find_each do |s|
  s.update(value: (s.value.rationalize - 0.1.rationalize).to_f)
end

However, I would like to use update_all as much as possible for faster updates, as performance is severely degraded when the somethings table has a large number of records.

  • The real question here is why you're using a float type column instead of a decimal which can properly handle normal arithmetical operations. – max Mar 09 '23 at 13:37
  • 1
    Thanks! I was not aware of the data type. Using decimal instead of float type solved it! – makoto_atarashi Mar 09 '23 at 13:51
  • I feel like this website could not be more apropos https://0.30000000000000004.com/ – engineersmnky Mar 09 '23 at 17:59
  • Does this answer your question? [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – engineersmnky Mar 09 '23 at 18:00
  • You can try using raw sql in update_all like this update_all("value = CAST(value AS DECIMAL(10, 9)) - 0.1"). – Zain Asif Mar 10 '23 at 03:58

0 Answers0