Ronan Lopes
Ronan Lopes

Reputation: 3398

Rails - Float precision

I have a float attribute, and I'm having problems with the precision. If save a value like "745.34", it saves correctly to database. However, if I try to save 4564523.845, for instance, it saves 4564520.0. Guess it's not a number that big that float doesn't suppor it. Some example of my console:

c.valor_total = 4564523.845
 => 4564523.845 
2.3.1 :034 > c.save
   (0.3ms)  BEGIN
  UnidadeConsumidora Load (0.3ms)  SELECT  `unidade_consumidoras`.* FROM `unidade_consumidoras` WHERE `unidade_consumidoras`.`id` = 28 LIMIT 1
  SQL (21.2ms)  UPDATE `contas` SET `valor_total` = 4564523.845, `updated_at` = '2016-10-20 17:28:20' WHERE `contas`.`id` = 28
   (70.4ms)  COMMIT
 => true 
2.3.1 :035 > c = Conta.find 28
  Conta Load (0.9ms)  SELECT  `contas`.* FROM `contas` WHERE `contas`.`id` = 28 LIMIT 1
 => #<Conta id: 28, unidade_consumidora_id: 28, razao_social: "DROGARIA ARAUJO S A", ano: 2016, mes: 8, numero_cliente: "7000042467", cnpj: "17.256.512/0001-16", consumo_kwh: "10942", vencimento: "2016-10-18", valor_total: 4564520.0, created_at: "2016-10-19 18:43:35", updated_at: "2016-10-20 17:28:20", pdf_conta: "ADOLPHO_COTTA.pdf", unidade_de_leitura: "07020129", cod_instalacao: "3000728720", logradouro: "PCA ALEXANDRE LANZA 141 CO .", bairro: "CENTRO", cep: "35700-040", municipio: "SETE LAGOAS", uf: "MG"> 
2.3.1 :036 > c.valor_total
 => 4564520.0

See that on update sql log the value is correct... so what can it be and how I fix it?

EDIT:

schema.rb for contas:

  create_table "contas", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.integer  "unidade_consumidora_id"
    t.string   "razao_social"
    t.integer  "ano"
    t.integer  "mes"
    t.string   "numero_cliente"
    t.string   "cnpj"
    t.string   "consumo_kwh"
    t.date     "vencimento"
    t.float    "valor_total",            limit: 24
    t.datetime "created_at",                        null: false
    t.datetime "updated_at",                        null: false
    t.string   "pdf_conta"
    t.string   "unidade_de_leitura"
    t.string   "cod_instalacao"
    t.string   "logradouro"
    t.string   "bairro"
    t.string   "cep"
    t.string   "municipio"
    t.string   "uf"
    t.index ["unidade_consumidora_id"], name: "index_contas_on_unidade_consumidora_id", using: :btree
  end

Upvotes: 2

Views: 4317

Answers (1)

Andrey Deineko
Andrey Deineko

Reputation: 52357

I am pretty sure you just have the "wrong" database type there.

Conta.columns_hash['valor_total'].type would most likely return "integer", whereas what you want to have is decimal if your goal is to store precise numbers.

I'd recommend to change the datatype:

change_column :contas, :valor_total, :decimal, precision: 5, scale: 2

EDIT

You have used float datatype, but did not specify the precision. Even though you probably (never saw a float db type used) could change it and specify it, I would still recommend to use decimal for such things, because it does not do any round up or so while calculations, so you will always have the most precise numbers you can get.

Upvotes: 2

Related Questions