การปัดเศษทศนิยมอัตโนมัติ


11

คำถามนั้นค่อนข้างง่าย ฉันต้องการคำนวณ 3 คอลัมน์ที่ผลลัพธ์กลางคือทศนิยมมากและฉันพบปัญหาในช่วงต้นกับ SQL Server โดยทั่วไปการปัดเศษทศนิยมโดยไม่คำนึงถึงการแปลง / แปลงใด ๆ

ตัวอย่างเช่นลองทำหารง่าย ๆ เป็น 1234/1233 เครื่องคิดเลขจะผลิต 1,00081103000811 แต่เมื่อฉันทำเช่นนี้บน SQL Server เราได้รับต่อไปนี้:

-- Result: rounded at 1.000811000... with trailing zeroes up until the 37 precision
SELECT CAST(CAST(1234 AS DEC(38,34))/CAST(1233 AS DEC(38,34)) AS DEC(38,37))

-- Result: rounded at 1.000811
SELECT CONVERT(DECIMAL(38,32), 1234)/CONVERT(DECIMAL(38,32),1233)

-- Correct result at 1,00081103000811
-- But this requires the zeroes to be put in manually when you don't
-- even know the precision of the end result
SELECT 1234.0/1233.00000000000000

เหตุใดการปัดเศษอัตโนมัตินี้จึงเกิดขึ้น และวิธีที่ดีที่สุดในการคำนวณค่าทศนิยมที่ยาวอย่างไม่น่าเชื่อคืออะไรเมื่อคุณไม่แน่ใจว่าจะมีจำนวนเท่าใด (ส่วน int หรือส่วนธันวาคม) เนื่องจากตารางสามารถมีค่าที่แตกต่างกันได้บ้าง

ขอบคุณ!

คำตอบ:


17

TL; DR

อย่าทำการคำนวณในภาษา SQL

อีกต่อไป

ขนาดและความแม่นยำผลหมายดีที่นี่ใน MSDN มันไม่ง่ายเลยจริงๆ อย่างไรก็ตามในแง่ง่ายความแม่นยำจะหายไปเมื่อระดับการป้อนข้อมูลสูงเนื่องจากเครื่องชั่งผลลัพธ์จะต้องลดลงถึง 38 ด้วยการวางความแม่นยำที่ตรงกัน

เพื่อยืนยันสิ่งต่าง ๆ

  • นักแสดงพิเศษของคุณในตัวอย่างแรกเพียงเพิ่มเลขศูนย์
  • การตัดปลายเกิดขึ้นตามลิงก์ MSDN ของฉัน (ตัวอย่างที่ 2)
  • ตัวอย่างที่ 3 ที่มีค่าคงที่มีค่าทศนิยมโดยนัยที่เพียงพอ (5,1) และ 18,14)
    นี่หมายความว่ามาตราส่วนผลลัพธ์และความแม่นยำไม่มีการตัดปลาย (ดูการระเบิด)

เพิ่มเติมเกี่ยวกับกรณีที่ 1 และ 3 ..

มาตราส่วนผลลัพธ์สำหรับการหารคือmax(6, s1 + p2 + 1):

  • ตัวอย่างแรกนี่คือ 77 ซึ่งลดลงถึง 38 ความแม่นยำถูกบังคับลงในทำนองเดียวกันขึ้นอยู่กับอย่างน้อย 6 (ดูนี้ )
  • ตัวอย่างที่สามนี่คือ 24 ดังนั้นไม่จำเป็นต้องปรับความแม่นยำ

คุณมีตัวเลือกบางอย่าง

  • คำนวณในรหัสลูกค้าเช่น. net
  • ใช้ฟังก์ชัน CLR เพื่อทำการคำนวณ. net
  • อยู่กับการสูญเสียความแม่นยำ
  • ใช้ float และใช้ชีวิตกับตัวเลข 15 ตัวที่ดีที่สุด

ดูในสิ่งนี้ใน SO /programming/423925/t-sql-decimal-division-accuracy/424052#424052


1

ไม่แน่ใจว่าสิ่งนี้จะช่วยได้หรือไม่ แต่สำหรับฉันคอลัมน์ตาราง temp ของฉันถูกตั้งค่าเป็นทศนิยมฉันกำลังผ่านการแปลง (ทศนิยม (15,2), 0.65) จากการแทรกลงใน temp_table นี่เป็นการปัดเศษอัตโนมัติฉันเปลี่ยนประเภทคอลัมน์เป็นทศนิยม (16,2) เพื่อให้ตรงกับสิ่งที่ผ่านไป ตารางกำลังจัดเก็บ 0.65


1

ฉันต้องหลีกเลี่ยง นี่คือสิ่งที่ฉันทำ:

-----------------------------------
DECLARE @DENIED INT  = 33443
DECLARE @PAID INT = 148353
DECLARE @PCT Decimal (6,2)

SET @PCT = (@DENIED * 100.00 / @PAID)  -- Instead of dividing by 100, I included decimals

SELECT
@DENIED AS DEN
,@PAID AS PAID
,@PCT AS PCT

ผล:

DEN PAID    PCT
-----   ----    -----
33443   148353  22.54   -- Instead of 22.00

หวังว่านี่จะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.