Kapan menggunakan float vs desimal


14

Saya sedang membangun API ini, dan database akan menyimpan nilai-nilai yang mewakili salah satu dari yang berikut:

  • persentase
  • rata-rata
  • menilai

Jujur saya tidak tahu bagaimana mewakili sesuatu yang kisarannya antara 0 dan 100% jumlahnya. Haruskah begitu

  • 0,00 - 1,00
  • 0,00 - 100,00
  • alternatif lain yang saya tidak tahu

Apakah ada pilihan yang jelas untuk itu? Cara global untuk merepresentasikan sesuatu pada basis data dari 0 hingga 100%? Lebih jauh lagi, apa yang benar untuk tipe itu, mengapung atau desimal?

Terima kasih.



5
Angka dapat disimpan dalam banyak cara. Tidak ada yang salah dengan menyimpan persentase menggunakan 0-100 atau 0-1. Yang penting adalah apa yang perlu Anda lakukan dengan angka, akurasi apa yang Anda butuhkan, dan sebagainya. Anda harus menjelaskan lebih banyak konteks sebelum jawaban yang baik dapat diberikan. Apakah Anda perlu menyimpan angka yang benar-benar representatif dengan sejumlah kecil angka desimal? Jika Anda rata-rata, Anda mendapatkan pecahan seperti sepertiga atau ketujuh. Apakah Anda perlu menyimpannya? Atau hanya sekitar? Bagaimana kira-kira? Apa yang akan kamu lakukan dengan mereka?
Eric Postpischil

1
Jika nilainya 0,00 hingga 100,00 dalam langkah 0,01 itu adalah 10001 nilai yang berbeda. Cukup gunakan a intuntuk mewakili ratusan atau dalam satuan Permyriad atau ‱.
chux

@ chux-ReinstateMonica - Ya, "bilangan bulat berskala" mungkin dilakukan, tetapi ceroboh.
Rick James

@ RickJames Mungkin. Saya belum menemukan bilangan bulat berskala sulit.
chux - Reinstate Monica

Jawaban:


4

Saya akan mengambil posisi sebaliknya.

FLOATadalah untuk angka perkiraan, seperti persentase, rata-rata, dll. Anda harus melakukan pemformatan saat Anda menampilkan nilai, baik dalam kode aplikasi atau menggunakan FORMAT()fungsi MySQL.

Jangan pernah menguji float_value = 1.3; ada banyak alasan mengapa itu akan gagal.

DECIMALharus digunakan untuk nilai moneter. DECIMALmenghindari pembulatan kedua saat nilai perlu dibulatkan ke dolar / sen / euro / dll. Akuntan tidak suka pecahan sen.

Implementasi MySQL DECIMALmemungkinkan 65 digit signifikan; FLOATmemberi sekitar 7 dan DOUBLEsekitar 16. 7 biasanya lebih dari cukup untuk sensor dan perhitungan ilmiah.

Adapun "persentase" - Kadang-kadang saya telah menggunakan TINYINT UNSIGNEDketika saya ingin mengkonsumsi hanya 1 byte penyimpanan dan tidak perlu banyak presisi; kadang saya menggunakan FLOAT(4 byte). Tidak ada tipe data yang disetel khusus untuk persentase. (Perhatikan juga, itu DECIMAL(2,0)tidak dapat menahan nilainya 100, jadi secara teknis Anda perlu DECIMAL(3,0).)

Atau kadang-kadang saya menggunakan nilai FLOATyang memegang antara 0 dan 1. Tapi kemudian saya harus memastikan untuk mengalikan dengan 100 sebelum menampilkan "persentase".

Lebih

Ketiga "persentase, rata-rata, rata" bau seperti mengapung, jadi itu akan menjadi pilihan pertama saya.

Satu kriteria untuk memutuskan tipe data ... Berapa banyak salinan nilai yang akan ada?

Jika Anda memiliki tabel miliar baris dengan kolom untuk persentase, pertimbangkan bahwa TINYINTakan membutuhkan 1 byte (total 1GB), tetapi FLOATakan mengambil 4 byte (total 4GB). OTOH, sebagian besar aplikasi tidak memiliki banyak baris, jadi ini mungkin tidak relevan.

Sebagai aturan 'umum', nilai "tepat" harus menggunakan beberapa bentuk INTatau DECIMAL. Hal-hal yang tidak tepat (perhitungan ilmiah, akar kuadrat, pembagian, dll) harus menggunakan FLOAT(atau DOUBLE).

Selanjutnya, format output biasanya harus dibiarkan ke ujung depan aplikasi. Artinya, meskipun "rata-rata" dapat menghitung menjadi "14.6666666 ...", layar akan menampilkan sesuatu seperti "14.7"; ini lebih bersahabat dengan manusia. Sementara itu, Anda memiliki nilai dasar untuk nanti memutuskan bahwa "15" atau "14,667" adalah format output yang disukai.

Rentang "0,00 - 100,00" dapat dilakukan dengan FLOAT dan menggunakan pemformatan output atau dengan DECIMAL(5,2)(3 byte) dengan pra-penentuan bahwa Anda akan selalu menginginkan ketepatan yang ditunjukkan .


3

Saya biasanya merekomendasikan untuk tidak menggunakan float. Angka titik apung memang mewakili angka dalam basis-2, yang menyebabkan beberapa angka (tepat) bulat dalam operasi atau perbandingan, karena angka-angka itu tidak dapat secara akurat disimpan dalam basis-2. Ini dapat menyebabkan perilaku mengejutkan.

Perhatikan contoh berikut :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

Basis-2 perbandingan angka 1.3gagal. Ini rumit.

Sebagai perbandingan, desimal memberikan representasi akurat dari angka hingga dalam kisarannya. Jika Anda mengubah floatke decimal(2, 1)dalam contoh di atas, Anda memang mendapatkan hasil yang diharapkan.


4
Jawaban ini salah dalam beberapa hal. "Sebagai perbandingan, desimal memiliki rentang yang lebih kecil tetapi memberikan representasi yang tepat dari angka hingga dalam rentang itu" salah: Desimal tidak mewakili ⅓ persis. “Beberapa (tepat, terbatas) angka-angka yang dikumpulkan” tidak benar; jumlahnya bukan "pembulatan". Konversi dan operasi lainnya dapat membulatkan. Mode pembulatan standar paling umum adalah pembulatan-ke-terdekat-ikatan-ke-genap, bukan pembulatan.
Eric Postpischil

4
Masalah dengan akurasi bukan karena "angka titik mengambang" tetapi hanya karena representasi numerik: Semua representasi numerik terbatas memiliki akurasi terbatas: Titik mengambang, titik tetap, bilangan bulat, bilangan bulat, bilangan bulat, bilangan desimal, biner, semuanya.
Eric Postpischil

2
Mendesah. Apa yang sudah kamu perbaiki? Komentar saya mengatakan jawabannya salah karena dikatakan desimal memberikan representasi angka yang tepat dalam kisarannya, tetapi kenyataannya tidak karena ia tidak memberikan representasi tepat ⅓. Perubahan mengatakan "akurat" dan bukan "tepat", tetapi mengapa tidak titik-biner sama baiknya — tidak ada yang tepat untuk ⅓, dan keduanya atau tidak sama-sama akurat, tergantung pada apa ambang batas Anda untuk keakuratan dan seberapa banyak presisi. mereka punya. Pertanyaannya menunjukkan rata-rata akan diwakili, dan rata-rata tiga hal memberi Anda angka seperti ⅓.
Eric Postpischil

4
Komentar itu mengatakan round-to-terdekat-ties-to-even adalah yang paling umum digunakan, tetapi jawabannya tetap mengatakan round-up. Jawabannya mengatakan perbandingan dapat dibulatkan, tetapi perbandingannya sempurna: Perbandingan selalu mengembalikan hasil yang benar secara matematis, tanpa pembulatan. (Beberapa bahasa pemrograman dapat mengonversi operan sebelum membandingkan, tetapi itu adalah operasi yang terpisah.)
Eric Postpischil

1
1/3 tidak dapat secara tepat direpresentasikan dalam biner atau desimal. Diskon 20% untuk $ 14,99 akan membutuhkan pembulatan sen pecahan.
Rick James

0

Perbedaan antara float dan desimal adalah presisi. Desimal dapat 100% secara akurat mewakili angka apa pun dalam ketepatan format desimal, sedangkan Float, tidak dapat secara akurat mewakili semua angka.

Gunakan Desimal untuk misalnya nilai terkait keuangan dan gunakan float untuk misalnya nilai terkait grafis


0

Saya sarankan menggunakan decimal(5,2)jika Anda akan menyimpannya dengan cara yang sama Anda akan menampilkannya karena decimaluntuk menjaga presisi yang tepat. (Lihat https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

Karena nilai floating-point adalah perkiraan dan tidak disimpan sebagai nilai yang tepat, upaya untuk memperlakukannya sebagai tepat dalam perbandingan dapat menyebabkan masalah. Mereka juga tergantung pada platform atau dependensi implementasi.

( https://dev.mysql.com/doc/refman/8.0/id/floating-point-types.html )

Nilai floating-point sebagaimana ditulis dalam pernyataan SQL mungkin tidak sama dengan nilai yang diwakili secara internal.

Untuk kolom DECIMAL, MySQL melakukan operasi dengan ketepatan 65 angka desimal, yang seharusnya memecahkan masalah ketidaktepatan paling umum.

https://dev.mysql.com/doc/refman/8.0/id/problems-with-float.html


0

Desimal: Dalam hal aplikasi keuangan, lebih baik menggunakan tipe Desimal karena memberi Anda tingkat akurasi yang tinggi dan mudah untuk menghindari kesalahan pembulatan

Ganda: Jenis Ganda mungkin merupakan tipe data yang paling sering digunakan untuk nilai riil, kecuali penanganan uang.

Float: Ini digunakan sebagian besar di perpustakaan grafis karena tuntutan yang sangat tinggi untuk kekuatan pemrosesan, juga digunakan situasi yang dapat menanggung kesalahan pembulatan.

Referensi: http://net-informations.com/q/faq/float.html


0
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G

*********************************************************************

@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

Desimal melakukan persis apa yang seharusnya dilakukan pada kasus ini, ia memotong sisanya, sehingga kehilangan 1/3 bagian.

Jadi untuk jumlah, desimal lebih baik, tetapi untuk divisi, float lebih baik, sampai titik tertentu, tentu saja. Maksud saya, menggunakan DECIMAL tidak akan memberi Anda "aritmatika gagal-bukti" dengan cara apa pun.

Saya harap ini akan membantu.


0

Dalam tsql: Float, 0,0 simpan sebagai 0 dan tidak perlu mendefinisikan setelah angka titik desimal, misalnya Anda tidak perlu menulis Float (4,2). Desimal, 0,0 simpan sebagai 0,0 dan memiliki opsi untuk mendefinisikan seperti desimal (4,2), saya sarankan 0,00-1,00, dengan melakukan ini, Anda dapat menghitung nilai persen tanpa kalikan dengan 100, dan jika Anda melaporkan kemudian mengatur tipe data kolom yang persen seperti MS Excel dan tampilan platform lainnya suka 0.5 -> 50%.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.