Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

SQL FLOAT:3 Poin yang Akan Membantu Anda Menghindari Kesalahan Matematika yang Aneh

Pernahkah Anda berpikir bahwa SQL bisa salah dalam matematika? Kedengarannya gila. Tetapi jika Anda telah menggunakan tipe data SQL FLOAT, Anda mungkin menemukan masalah yang akan saya tunjukkan kepada Anda.

Pertimbangkan ini. 0.1 + 0.2 seharusnya 0.3, kan? Tapi periksa ini menggunakan tipe data SQL FLOAT.

DECLARE @f1 FLOAT = 0.1
DECLARE @f2 FLOAT = 0.2

SELECT CASE WHEN @f1 + @f2 = .3 THEN 1 ELSE 0 END

Hasil yang benar adalah 1. Tapi periksa Gambar 1.

Apakah saya mendapat perhatian Anda sekarang? Saya yakin berharap begitu. Sangat menakutkan untuk bergantung pada sistem yang tidak memberi kita matematika yang benar. Namun artikel ini akan membantu Anda menghindarinya.

Ada beberapa pekerjaan yang harus dilakukan. Kita harus mulai dari apa itu tipe data FLOAT.

Apa itu Tipe Data SQL FLOAT?

Tipe data SQL FLOAT adalah perkiraan tipe data numerik yang digunakan untuk angka floating-point. Mereka dapat menyimpan nomor yang sangat besar atau sangat kecil. Mereka juga digunakan untuk komputasi yang membutuhkan waktu pemrosesan yang cepat.

Semua ini harus dibayar dengan hilangnya presisi. Selanjutnya, Anda tidak dapat mengatakan di mana titik desimal akan ditempatkan setelah perhitungan – itu mengambang . Sementara itu, angka eksak seperti DECIMAL akan memiliki posisi titik desimal tetap.

Bagaimana Anda Mendeklarasikan Tipe Data SQL FLOAT

Sintaksnya adalah FLOAT[(n)], di mana n adalah jumlah bit yang digunakan untuk menyimpan mantissa dari bilangan floating-point dalam notasi ilmiah. Itu juga menentukan presisi dan ukuran penyimpanan. Nilai yang mungkin untuk n antara 1 sampai 53. Perhatikan bahwa n adalah opsional.

Ini contohnya:

DECLARE @floatValue1 FLOAT;   -- Float variable without the number of bits
DECLARE @floatValue2 FLOAT(3) -- Float variable with 3 bits 

Jika Anda tidak menentukan n , defaultnya adalah 53. Itu juga merupakan nilai maksimum. Selanjutnya, FLOAT(53) adalah angka floating-point presisi ganda atau binary64. Selain menggunakan FLOAT(53), kamu juga bisa mendeklarasikannya sebagai DOUBLE PRECISION.

3 deklarasi berikut secara fungsional setara:

DECLARE @double1 FLOAT(53); 
DECLARE @double2 FLOAT;
DECLARE @double3 DOUBLE PRECISION;

Tabel menunjukkan jumlah bit dan ukuran penyimpanan yang sesuai.

Nilai n Ukuran Penyimpanan
1 hingga 24 4 byte
25 hingga 53 8 byte

Apakah SQL FLOAT dan REAL Sama?

REAL juga FLOAT (24). Ini juga disebut sebagai presisi tunggal atau biner32.

Mengapa Mengetahui Ini Penting

Mengetahui bahwa ini adalah angka perkiraan akan menghentikan Anda menggunakannya untuk perhitungan yang membutuhkan akurasi. Apakah Anda juga peduli dengan penyimpanan dan memori? Gunakan REAL atau FLOAT(24) jika Anda tidak membutuhkan nilai yang terlalu besar atau terlalu kecil.

Apa Perbedaan Antara FLOAT dan DECIMAL?

FLOAT adalah perkiraan numerik. DECIMAL adalah angka eksak. Berikut ringkasan perbedaan dalam Tabel:

FLOAT DECIMAL
Poin Desimal Dapat ditempatkan di mana saja dalam digit Posisi tetap
Batas Maksimum 38 digit atau 99,999,999,999,999,999,999,999,999,999,999,999,999 FLOAT(53) memiliki jangkauan maksimum 1,79E+308 atau 179 diikuti oleh 306 nol
Penyimpanan Maksimum 8 byte Maksimum 17 byte
Hasil Komputasi Perkiraan Tepat
Pemeriksaan perbandingan Jangan gunakan =atau <>. Hindari saat pembulatan =atau <> operator. Bagus untuk pembulatan

Anda sudah melihat pada Gambar 1 bagaimana menghitung nomor FLOAT dapat memiliki hasil yang aneh. Jika Anda mengubah tipe data menjadi DECIMAL seperti ini:

DECLARE @d1 DECIMAL(2,1) = 0.1
DECLARE @d2 DECIMAL(2,1) = 0.2

SELECT CASE WHEN @d1 + @d2 = 0.3 THEN 1 ELSE 0 END 

Hasilnya akan benar.
Menggunakan operator pertidaksamaan juga merupakan masalah. Lihat loop di bawah ini.

DECLARE @floatValue FLOAT(1) = 0.0

WHILE @floatValue <> 5.0
BEGIN
	PRINT @floatValue;
	SET @floatValue += 0.1;
END 

Bagaimana menurutmu? Lihat Gambar 2 di bawah.

Ledakan! Lingkaran tak terbatas! Kondisi pertidaksamaan akan selalu benar. Jadi, pilihan logisnya adalah mengubah jenisnya menjadi DECIMAL.

DECLARE @decimalValue DECIMAL(2,1) = 0.0

WHILE @decimalValue <> 5.0
BEGIN
	PRINT @decimalValue;
	SET @decimalValue += 0.1;
END 

Kode di atas pasti akan berhenti ketika @decimalValue sama dengan 5.0. Lihat sendiri pada Gambar 3 di bawah ini.

Bagus! Tetapi jika Anda masih bersikeras pada FLOAT, ini akan bekerja dengan baik tanpa infinite loop.

DECLARE @floatValue FLOAT(1) = 0.0

WHILE @floatValue < 5.0
BEGIN
	PRINT @floatValue;
	SET @floatValue += 0.1;
END

Sementara itu, pembulatan juga tidak aktif. Pertimbangkan hal berikut:

DECLARE @value FLOAT(2) = 1.15

SELECT ROUND(@value, 1)  -- This will result to 1.1

Alih-alih 1,20, hasil kode menjadi 1.1. Tetapi jika Anda menggunakan DECIMAL, hasilnya akan benar.

DECLARE @value DECIMAL(3,2) = 1.15

SELECT ROUND(@value, 1)  -- This will result in 1.2 or 1.20

Bila FLOAT Benar, dan DECIMAL Tidak

Apakah angka yang tepat TIDAK begitu tepat sepanjang waktu? Untuk mereproduksi masalah ini, kami akan menggunakan perhitungan, dan kemudian kami membalikkannya. Pertama, mari kita siapkan datanya.

CREATE TABLE ExactNumerics1
(
	fixed1 DECIMAL(8,4),
	fixed2 DECIMAL(8,4),
	fixed3 DECIMAL(8,4),
	calcValue1 AS fixed3 / fixed1 * fixed2
)
GO

INSERT INTO ExactNumerics1
(fixed1,fixed2,fixed3)
VALUES
(54,0.03,1*54/0.03)

Tabel di atas akan menggunakan nilai tetap untuk 2 kolom pertama. Kolom ketiga akan memiliki perhitungan. Akhirnya, kolom keempat, yang merupakan kolom yang dihitung, akan melakukan perhitungan terbalik. Hasil yang benar dalam kolom yang dihitung seharusnya 1.

Sekarang, untuk membandingkannya dengan FLOAT, mari kita buat tabel dan data yang serupa.

CREATE TABLE ApproxNumerics1
(
	float1 FLOAT(2),
	float2 FLOAT(2),
	float3 FLOAT(2),
	calcValue1 AS float3 / float1 * float2 
)

INSERT INTO ApproxNumerics1
(float1, float2, float3)
VALUES
(54,0.03,1*54/0.03)

Mari kita bertanya.

SELECT * FROM ApproxNumerics1
SELECT * FROM ExactNumerics1

Hasil? Lihat Gambar 4.

Apa yang terjadi disini? FLOAT melakukannya dengan benar, tetapi DECIMAL tidak. Ada yang tidak beres.

KONVERSI IMPLISIT MELAKUKANNYA LAGI

Konversi implisit terjadi karena SQL memaafkan. Saat tipe data yang berbeda digunakan dalam penghitungan, SQL Server mencoba mengonversinya menggunakan konversi implisit di belakang kami.

Apakah konversi benar-benar terjadi? Selain itu, setiap kolom di ExactNumerics1 tabel adalah DECIMAL.

Mari kita periksa struktur tabel ExactNumerics1 tabel di SQL Server Management Studio:

Perhatikan area kotak merah pada Gambar 3. Kolom yang dihitung adalah DECIMAL(30,17), bukan DECIMAL(8,4). Menurut dokumentasi resmi, 2 kolom DECIMAL dengan presisi dan skala yang berbeda adalah 2 tipe data yang berbeda . Lihat sendiri di sini. Karena perbedaannya, diperlukan konversi. Jadi, konversi implisit ikut berperan.

Bagaimana jika mereka berbeda dan konversi implisit telah terjadi?

Sekali lagi, berdasarkan dokumentasi resmi, kehilangan presisi atau skala dapat terjadi selama konversi implisit . Dengan demikian, CAST eksplisit diperlukan. Perhatikan tipe data DECIMAL dalam tabel konversi dalam referensi tersebut.

Beberapa kerugian baru saja terjadi di sini. Jika kolom terhitung juga DECIMAL(8,4), konversi implisit tidak terjadi.

Untuk menghindari konversi implisit, ikuti dokumentasi resmi. Struktur tabel seharusnya seperti ini:

CREATE TABLE ExactNumerics2
(
	fixed1 DECIMAL(8,4),
	fixed2 DECIMAL(8,4),
	fixed3 DECIMAL(8,4),
	calcValue1 AS CAST(fixed3 / fixed1 * fixed2 AS DECIMAL(8,4)) -- the explicit CAST
)

CAST eksplisit di kolom terhitung memastikan bahwa tipe data konsisten. Jika kita juga mengikuti struktur ini dan memasukkan data yang sama, hasilnya akan benar. Lihat keluaran baru pada Gambar 6 di bawah ini.

Pada akhirnya, angka pasti tidak akan tepat jika konversi implisit terjadi antara 2 atau lebih nilai DECIMAL.

Mengapa Mengetahui Ini Penting

Ini memberi Anda gambaran tentang apa yang Anda butuhkan untuk tabel dan variabel Anda. Selain itu, konversi implisit dapat membuat angka yang tepat menjadi gila. Jadi, definisikan presisi dan skala secara eksplisit dan konsistenlah dengannya dalam perhitungan Anda.

Haruskah Saya Menggunakan SQL FLOAT untuk Data Keuangan?

Saat menghitung persentase di setiap irisan grafik pai, jumlahnya harus 100%. Total dalam ringkasan dan laporan rinci juga harus konsisten. Jika keakuratan hasil sangat penting, perkiraan tipe data seperti FLOAT tidak akan berhasil. Pilihan logis untuk ini adalah DECIMAL.

Tapi tetap ada pertanyaan.

Kapan Anda Harus Menggunakan FLOAT?

Gunakan FLOAT untuk data yang membutuhkan nilai astronomi seperti jarak antar galaksi. Sementara itu, tipe data DECIMAL akan mengalami overflow aritmatika dengan tipe data ini. Nilai kecil seperti diameter inti atom juga akan cocok menggunakan FLOAT. Data ilmiah dan nilai lain yang tidak memerlukan presisi juga dapat memanfaatkan FLOAT.

Mengapa Mengetahui Ini Penting

Kami tidak mengatakan bahwa FLOAT itu buruk dan DECIMAL itu baik atau sebaliknya. Mengetahui kasus penggunaan yang benar untuk masing-masing akan memberi Anda dan pengguna Anda hasil yang diinginkan. Dan sekali lagi, Anda ingin pengguna Anda senang, bukan?

Kesimpulan

Pada akhirnya, kita semua ingin melakukan pekerjaan kita dan menjadi ahli dalam hal itu. Matematika akan selalu menjadi bagian dari pekerjaan kita. Dan mengetahui tipe data numerik yang benar juga akan membantu kita menghadapinya. Tidak sulit jika Anda tahu apa yang Anda lakukan.

Saya harap artikel ini membantu Anda menghindari matematika aneh di SQL Server.

Apakah Anda memiliki hal lain untuk ditambahkan? Kemudian, beri tahu kami di bagian Komentar. Bagikan ini juga di platform media sosial favorit Anda.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tindak lanjut pada opsi kursor

  2. Bagaimana cara menggunakan COUNT dalam SQL?

  3. Lebih baik ALTER daripada DROP

  4. Apakah Anda selalu membutuhkan database untuk aplikasi Anda?

  5. Cara Mengembalikan Database Dengan Backup Manager