---
title: "Rails adds accurate numerical validation"
description:
  "Rails now avoids converting integer as a string into float when validating
  numericality"
canonical_url: "https://www.bigbinary.com/blog/rails-now-avoids-converting-integer-as-a-string-into-float-when-validating-numericality"
markdown_url: "https://www.bigbinary.com/blog/rails-now-avoids-converting-integer-as-a-string-into-float-when-validating-numericality.md"
---

# Rails adds accurate numerical validation

Rails now avoids converting integer as a string into float when validating
numericality

- Author: Sushant Mittal
- Published: October 23, 2017
- Categories: Rails

Let's see an example of numerical validation of very large numbers.

```ruby
class Score
  validates :total, numericality: { less_than_or_equal_to: 10_000_000_000_000_000 }
end


> score = Score.new(total: (10_000_000_000_000_000 + 1).to_s)
> score.total
#=> 1.0e+16

> score.invalid?
#=> false
```

Here, we have added numerical validation on `total` column of `Score` model that
it should be less than `10_000_000_000_000_000`.

After that we have created one instance of this model with `total` greater than
allowed value. This should result in an invalid object as it violates the
numericality criteria.

But it is still valid. We can also see that value of `total` has been converted
into floating number instead of integer. This happens because Rails used to
[convert the input to float](https://github.com/rails/rails/blob/46bf9eea533f8a2fedbb0aaad12cae1c5a4b9612/activemodel/lib/active_model/validations/numericality.rb#L73)
[if it was not](https://github.com/rails/rails/blob/46bf9eea533f8a2fedbb0aaad12cae1c5a4b9612/activemodel/lib/active_model/validations/numericality.rb#L39)
already numeric.

The real problem is here is that the floating point comparison of the Ruby
language itself which is not accurate for very large numbers.

```ruby
>> a = (10_000_000_000_000_000 + 1).to_s
=> "10000000000000001"
>> b = Kernel.Float a
=> 1.0e+16
>> c = b + 1
=> 1.0e+16
>> c < b
=> false
>> c > b
=> false
>>
```

This issue has been fixed in Rails
[here](https://github.com/rails/rails/commit/b0be7792adf58e092b7f615ecbf3339ea70ee689).
Now, if the given string input can be treated as integer, then
[an integer value is returned instead of float](https://github.com/rails/rails/blob/1ceaf7db5013a233bdc671b3f46583c4c1189fe1/activemodel/lib/active_model/validations/numericality.rb#L88).
This makes sure that the comparison works correctly.

```ruby
# Rails 5.2

> score = Score.new(total: (10_000_000_000_000_000 + 1).to_s)
> score.total
#=> 10000000000000001

> score.invalid?
#=> true
```

This change is present in Rails 5.2 and above. It also backported to Rails 5.1
and Rails 5.0 branches.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-now-avoids-converting-integer-as-a-string-into-float-when-validating-numericality)
