ทำไม Math.Round (2.5) ถึงกลับ 2 แทน 3


415

ใน C # ผลลัพธ์ของMath.Round(2.5)คือ 2

มันควรจะเป็น 3 ใช่ไหม ทำไมถึงเป็น 2 แทนใน C #


5
มันเป็นคุณสมบัติจริงๆ ดู <a href=" msdn.microsoft.com/en-us/library/..เอกสารMSDN</a>การปัดเศษชนิดนี้เรียกว่าการปัดเศษของนายธนาคารสำหรับวิธีการแก้ไขมี <a href = " msdn microsoft.com/en-us/library/…โอเวอร์โหลด </a> ที่อนุญาตให้ผู้โทรระบุวิธีการปัดเศษ
Joe

1
เห็นได้ชัดว่าวิธีการปัดเศษเมื่อถูกขอให้ปัดเศษตัวเลขระหว่างจำนวนเต็มสองตัวจะส่งกลับจำนวนเต็มคู่ ดังนั้น Math.Round (3.5) จะให้ผลตอบแทน 4. ดูบทความนี้
Matthew Jones

20
Math.Round(2.5, 0, MidpointRounding.AwayFromZero);
Robert Durgin

SQL Server ปัดเศษแบบนั้น ผลการทดสอบที่น่าสนใจเมื่อมีการทดสอบหน่วย C # ตรวจสอบการปัดเศษที่ทำใน T-SQL
idstam

7
@ ระบุว่าไม่ใช่ข้อผิดพลาด มันเป็นวิธีการทำงานของเลขทศนิยม 1.005ไม่สามารถแสดงเป็นคู่ได้อย่างแน่นอน 1.00499...มันอาจจะ หากคุณใช้Decimalปัญหานี้จะหายไป การดำรงอยู่ของ Math.Round เกินพิกัดที่ใช้จำนวนทศนิยมเป็นสองเท่าเป็นตัวเลือกการออกแบบที่น่าสงสัย IMO เนื่องจากมันจะไม่ค่อยทำงานในทางที่มีความหมาย
CodesInChaos

คำตอบ:


560

ประการแรกนี่จะไม่เป็นข้อผิดพลาด C # ต่อไป - มันจะเป็น. NET C # เป็นภาษา - มันไม่ได้ตัดสินใจว่าMath.Roundจะนำไปใช้อย่างไร

และประการที่สองไม่ใช่ - ถ้าคุณอ่านเอกสารคุณจะเห็นว่าการปัดเศษเริ่มต้นคือ "ปัดเศษเป็นคู่" (ปัดเศษของนายธนาคาร):

Return Value
Type: System.Double
จำนวนเต็มที่ใกล้ที่สุด หากส่วนประกอบที่เป็นเศษส่วนของ a อยู่ครึ่งทางระหว่างจำนวนเต็มสองตัวหนึ่งตัวหนึ่งจะเป็นเลขคู่กับเลขคี่อื่น ๆ ดังนั้นเลขคู่จะถูกส่งคืน โปรดทราบว่าวิธีการนี้จะส่งกลับประเภทหนึ่งDoubleแทน

ข้อสังเกต
พฤติกรรมของวิธีการนี้เป็นไปตามมาตรฐาน IEEE 754, หมวดที่ 4 การปัดเศษนี้บางครั้งเรียกว่าการปัดเศษเป็นใกล้ที่สุดหรือปัดเศษของนายธนาคาร มันลดข้อผิดพลาดในการปัดเศษซึ่งเป็นผลมาจากการปัดเศษค่ากึ่งกลางในทิศทางเดียวอย่างสม่ำเสมอ

คุณสามารถระบุว่าMath.Roundควรปัดเศษจุดกึ่งกลางอย่างไรโดยใช้โอเวอร์โหลดซึ่งรับMidpointRoundingค่า มีหนึ่งโอเวอร์โหลดที่MidpointRoundingสอดคล้องกับโอเวอร์โหลดแต่ละอันที่ไม่มี:

ไม่ว่าการเริ่มต้นนี้จะถูกเลือกอย่างดีหรือไม่ก็ตาม ( MidpointRoundingถูกนำมาใช้ใน. NET 2.0 เท่านั้นก่อนหน้านี้ฉันไม่แน่ใจว่ามีวิธีที่ง่ายในการใช้งานพฤติกรรมที่ต้องการโดยไม่ต้องทำด้วยตัวเอง) โดยเฉพาะประวัติแสดงให้เห็นว่ามันไม่ใช่พฤติกรรมที่คาดหวัง - และในกรณีส่วนใหญ่ บาปสำคัญในการออกแบบ API ฉันเห็นได้ว่าเหตุใดการปัดเศษของ Banker มีประโยชน์ ... แต่ก็ยังแปลกใจกับหลาย ๆ คน

คุณอาจสนใจดู Java เทียบเท่า enum ( RoundingMode) ซึ่งมีตัวเลือกมากขึ้น (มันไม่เพียงจัดการกับจุดกึ่งกลาง)


4
ฉันไม่รู้ว่านี่เป็นข้อผิดพลาดหรือเปล่าฉันคิดว่ามันเป็นเพราะการออกแบบตั้งแต่. 5 ใกล้เคียงกับจำนวนเต็มต่ำสุดที่ใกล้ที่สุดเพราะมันเป็นจำนวนเต็มที่ใกล้เคียงที่สุด
Stan R.

3
ฉันจำพฤติกรรมนี้ใน VB ได้ก่อนที่. NET จะถูกนำไปใช้
John Fiala

7
อันที่จริง IEEE Standard 754 ตอนที่ 4 เป็นสถานะเอกสารประกอบ
Jon Skeet

2
ฉันถูกไฟไหม้เมื่อไม่นานมานี้และคิดว่ามันเป็นความบ้าคลั่งที่แท้จริงเช่นกัน โชคดีที่พวกเขาเพิ่มวิธีการระบุการปัดเศษที่เราทุกคนเรียนรู้ในระดับชั้นประถมศึกษา MidPointRounding
Shea

26
+1 สำหรับ "มันไม่ใช่พฤติกรรมที่คาดหวัง [... ] ที่เป็นบาปสำคัญในการออกแบบ API"
BlueRaja - Danny Pflughoeft

215

ที่เรียกว่าการปัดเศษที่จะได้ (หรือนายธนาคารปัดเศษ) (MidpointRounding.ToEven)ซึ่งเป็นกลยุทธ์การปัดเศษที่ถูกต้องเพื่อลดข้อผิดพลาดที่เกิดขึ้นในเงินก้อน ทฤษฎีก็คือว่าถ้าคุณเสมอรอบจำนวน 0.5 ไปในทิศทางเดียวกัน, ข้อผิดพลาดที่จะเกิดขึ้นได้เร็วขึ้น (รอบต่อแม้ควรจะลดนั้น) (ก)

ไปที่ลิงก์เหล่านี้สำหรับคำอธิบาย MSDN ของ:

  • Math.Floorซึ่งปัดลงไปทางลบอนันต์
  • Math.Ceilingซึ่งปัดขึ้นไปหาอนันต์บวก
  • Math.Truncateซึ่งปัดขึ้นหรือลงสู่ศูนย์
  • Math.Roundซึ่งจะปัดเศษเป็นจำนวนเต็มที่ใกล้ที่สุดหรือจำนวนตำแหน่งทศนิยมที่ระบุ คุณสามารถระบุพฤติกรรมได้ถ้ามันมีระยะห่างเท่ากันระหว่างความเป็นไปได้สองอย่างเช่นการปัดเศษเพื่อให้ตัวเลขสุดท้ายเป็นเลขคู่ (" Round(2.5,MidpointRounding.ToEven)" กลายเป็น 2) หรือเพื่อให้ห่างจากศูนย์ (" Round(2.5,MidpointRounding.AwayFromZero)" กลายเป็น 3)

แผนภาพและตารางต่อไปนี้อาจช่วยได้:

-3        -2        -1         0         1         2         3
 +--|------+---------+----|----+--|------+----|----+-------|-+
    a                     b       c           d            e

                       a=-2.7  b=-0.5  c=0.3  d=1.5  e=2.8
                       ======  ======  =====  =====  =====
Floor                    -3      -1      0      1      2
Ceiling                  -2       0      1      2      3
Truncate                 -2       0      0      1      2
Round(ToEven)            -3       0      0      2      3
Round(AwayFromZero)      -3      -1      0      2      3

โปรดทราบว่าRoundมีประสิทธิภาพมากกว่าที่คิดเพียงเพราะมันสามารถปัดเศษทศนิยมตามจำนวนที่กำหนดได้ ส่วนอื่น ๆ ทั้งหมดจะปัดเป็นศูนย์ทศนิยมเสมอ ตัวอย่างเช่น:

n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven);       // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15

ด้วยฟังก์ชั่นอื่น ๆ คุณจะต้องใช้เทคนิคการทวีคูณ / หารเพื่อให้ได้เอฟเฟกต์เดียวกัน:

c = System.Math.Truncate (n * 100) / 100;                    // 3.14
d = System.Math.Ceiling (n * 100) / 100;                     // 3.15

(a)แน่นอนว่าทฤษฎีนั้นขึ้นอยู่กับความจริงที่ว่าข้อมูลของคุณมีการกระจายของค่าที่เป็นธรรมในส่วนเท่า ๆ กัน (0.5, 2.5, 4.5, ... ) และครึ่งคี่ (1.5, 3.5, ... )

ถ้าทุกคนว่า "ครึ่งค่า" เป็น evens (ตัวอย่าง), ข้อผิดพลาดที่จะสะสมอย่างรวดเร็วเพียงเท่าถ้าคุณกลมเสมอ


3
รู้จักกันในชื่อ
Rounder

คำอธิบายที่ดี! ฉันต้องการดูด้วยตนเองว่าข้อผิดพลาดสะสมอย่างไรและฉันเขียนสคริปต์ที่แสดงว่าค่าที่ปัดเศษโดยการปัดเศษของธนาคารในระยะยาวมีผลรวมและค่าเฉลี่ยใกล้เคียงกับค่าดั้งเดิมเหล่านี้มาก github.com/AmadeusW/RoundingDemo (ภาพมีแปลง)
Amadeusz Wieczorek

อีกไม่นานหลังจากนั้น: ไม่ควรเลือกe(= 2.8) ถูกกว่า2เห็บ?
superjos

วิธีง่ายๆในการจดจำและสมมติว่าสถานที่ที่สิบคือ 5: - สถานที่และสถานที่ที่สิบทั้งหมดแปลก = รอบขึ้น - สถานที่และสถานที่ที่สิบผสม = รอบลง * ศูนย์ไม่แปลก * กลับสำหรับจำนวนลบ
Arkham Angel

@ArkhamAngel ที่จริงดูเหมือนยากที่จะจำได้มากกว่าแค่ "ทำให้หลักสุดท้ายแม้" :-)
paxdiablo

42

จากMSDN, Math.Round (double a)จะส่งคืน:

จำนวนเต็มที่ใกล้ที่สุด หากส่วนประกอบที่เป็นเศษส่วนของ a อยู่ครึ่งทางระหว่างจำนวนเต็มสองจำนวนหนึ่งตัวหนึ่งจะเป็นเลขคู่กับเลขคี่อื่น ๆ ดังนั้นเลขคู่จะถูกส่งคืน

... และ 2.5 จากนั้นครึ่งทางระหว่าง 2 และ 3 จะถูกปัดเศษเป็นจำนวนคู่ (2) สิ่งนี้เรียกว่าการปัดเศษของธนาคาร (หรือปัดเศษเป็นคู่) และเป็นมาตรฐานการปัดเศษที่ใช้กันทั่วไป

บทความ MSDN เดียวกัน:

พฤติกรรมของวิธีการนี้เป็นไปตามมาตรฐาน IEEE 754 ส่วนที่ 4 การปัดเศษนี้บางครั้งเรียกว่าการปัดเศษเป็นใกล้ที่สุดหรือปัดเศษของนายธนาคาร มันลดข้อผิดพลาดในการปัดเศษซึ่งเป็นผลมาจากการปัดเศษค่ากึ่งกลางในทิศทางเดียวอย่างสม่ำเสมอ

คุณสามารถระบุพฤติกรรมการปัดเศษที่แตกต่างกันโดยเรียกโอเวอร์โหลดของ Math.Round ที่ใช้MidpointRoundingโหมด


37

คุณควรตรวจสอบ MSDN สำหรับMath.Round:

พฤติกรรมของวิธีการนี้เป็นไปตามมาตรฐาน IEEE 754 ส่วนที่ 4 การปัดเศษนี้บางครั้งเรียกว่าการปัดเศษเป็นใกล้ที่สุดหรือปัดเศษของนายธนาคาร

คุณสามารถระบุพฤติกรรมการMath.Roundใช้งานโอเวอร์โหลดได้:

Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3

Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2

31

ลักษณะของการปัดเศษ

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

โดยทั่วไปหรือการปัดเศษ 'คณิตศาสตร์' เป็นที่ชัดเจนว่า 2.1, 2.2, 2.3 และ 2.4 รอบถึง 2.0; และ 2.6, 2.7, 2.8 และ 2.9 ถึง 3.0

นั่นเหลือ 2.5 ซึ่งไม่ใกล้ 2.0 ถึงกว่า 3.0 ขึ้นอยู่กับคุณที่จะเลือกระหว่าง 2.0 และ 3.0 ซึ่งจะใช้ได้อย่างเท่าเทียมกัน

สำหรับตัวเลขลบ -2.1, -2.2, -2.3 และ -2.4 จะกลายเป็น -2.0; และ -2.6, 2.7, 2.8 และ 2.9 จะกลายเป็น -3.0 ภายใต้การปัดเศษทางคณิตศาสตร์

สำหรับ -2.5 จำเป็นต้องมีตัวเลือกระหว่าง -2.0 ถึง -3.0

การปัดเศษในรูปแบบอื่น

'การปัดเศษขึ้น' ใช้ตัวเลขใด ๆ ที่มีทศนิยมและทำให้เป็นเลข 'เต็ม' ถัดไป ดังนั้นไม่เพียง แต่ทำ 2.5 และ 2.6 รอบถึง 3.0 แต่ต้องทำ 2.1 และ 2.2

การปัดเศษขึ้นจะย้ายทั้งจำนวนบวกและลบออกห่างจากศูนย์ เช่น. 2.5 ถึง 3.0 และ -2.5 ถึง -3.0

'ปัดเศษลง' ปัดเศษตัวเลขด้วยการตัดตัวเลขที่ไม่ต้องการออก นี่คือผลของการย้ายตัวเลขไปสู่ศูนย์ เช่น. 2.5 ถึง 2.0 และ -2.5 ถึง -2.0

ใน "การปัดเศษของนายธนาคาร" - ในรูปแบบที่พบบ่อยที่สุด - .5 ที่จะถูกปัดเศษจะถูกปัดขึ้นหรือลงเพื่อให้ผลลัพธ์ของการปัดเศษนั้นเป็นเลขคู่เสมอ ดังนั้น 2.5 รอบถึง 2.0, 3.5 ถึง 4.0, 4.5 ถึง 4.0, 5.5 ถึง 6.0, และอื่น ๆ

'Alternate rounding' สลับกระบวนการสำหรับ 0.5 ระหว่างการปัดเศษลงและปัดเศษขึ้น

'การปัดเศษแบบสุ่ม' ปัดเศษขึ้นหรือลง 0.5 โดยการสุ่มทั้งหมด

สมมาตรและไม่สมมาตร

ฟังก์ชันการปัดเศษถูกเรียกว่า 'สมมาตร' ถ้ามันปัดเศษตัวเลขทั้งหมดให้ห่างจากศูนย์หรือปัดตัวเลขทั้งหมดให้เป็นศูนย์

ฟังก์ชั่นคือ 'ไม่สมมาตร' ถ้าปัดเศษจำนวนบวกไปทางศูนย์และจำนวนลบห่างจากศูนย์ .. เช่น 2.5 ถึง 2.0; และ -2.5 ถึง -3.0

ยังไม่สมมาตรเป็นฟังก์ชันที่ปัดเศษตัวเลขบวกออกจากศูนย์และตัวเลขลบเป็นศูนย์ เช่น. 2.5 ถึง 3.0; และ -2.5 ถึง -2.0

คนส่วนใหญ่คิดว่าการปัดเศษแบบสมมาตรโดยที่ -2.5 จะถูกปัดเศษเป็น -3.0 และ 3.5 จะถูกปัดเศษเป็น 4.0 (ใน C #Round(AwayFromZero))


28

ค่าเริ่มต้นMidpointRounding.ToEvenหรือการปัดเศษของธนาคาร ( 2.5 กลายเป็น 2, 4.5 กลายเป็น 4 เป็นต้น ) ทำให้ฉันได้รับก่อนที่จะเขียนรายงานการบัญชีดังนั้นฉันจะเขียนคำสองสามคำเกี่ยวกับสิ่งที่ฉันค้นพบก่อนหน้านี้และจากการมองหา โพสต์นี้

ใครคือนายธนาคารเหล่านี้ที่ปัดเศษตัวเลขให้เท่ากัน (อาจเป็นนายธนาคารชาวอังกฤษ!)?

จากวิกิพีเดีย

ที่มาของคำว่าการปัดเศษของนายธนาคารยังคงคลุมเครือมากขึ้น หากวิธีการปัดเศษนี้เป็นมาตรฐานในธนาคารหลักฐานก็พิสูจน์ได้ยากมาก ในทางตรงกันข้ามส่วนที่ 2 ของรายงานของคณะกรรมาธิการยุโรปการแนะนำของเงินยูโรและการปัดเศษของสกุลเงินแสดงให้เห็นว่าก่อนหน้านี้ไม่มีวิธีการมาตรฐานในการปัดเศษในธนาคาร และระบุว่าควรปัดเศษจำนวน "ครึ่งทาง"

ดูเหมือนจะเป็นวิธีที่แปลกมากในการปัดเศษโดยเฉพาะกับธนาคารเว้นแต่ว่าธนาคารจะใช้เพื่อรับเงินฝากจำนวนมาก ฝากเงิน 2.4m แต่เราจะเรียกมันว่า£ 2m

มาตรฐาน IEEE 754 ย้อนกลับไปในปี 1985 และให้การปัดเศษทั้งสองวิธี แต่มีนายธนาคารเป็นผู้แนะนำตามมาตรฐาน นี้บทความวิกิพีเดียมีรายชื่อยาวของวิธีการใช้ภาษาการปัดเศษ (ฉันถูกต้องถ้าใด ๆ ของด้านล่างนี้มีผิด) และส่วนใหญ่ไม่ได้ใช้ธนาคาร แต่ปัดเศษคุณกำลังสอนอยู่ที่โรงเรียน:

  • C / C ++รอบ () จาก math.h ปัดเศษออกจากศูนย์ (ไม่ใช่การปัดเศษของนายธนาคาร)
  • Java Math.Roundปัดเศษจากศูนย์ (ซึ่งจะเพิ่มผลลัพธ์, เพิ่ม 0.5, ปลดเปลื้องให้เป็นจำนวนเต็ม) มีทางเลือกอื่นในBigDecimal
  • Perlใช้วิธีการคล้ายกับ C
  • Javascript เหมือนกับ Math.Round ของ Java

ขอบคุณสำหรับข้อมูล. ฉันไม่เคยตระหนักถึงสิ่งนี้ ตัวอย่างของคุณเกี่ยวกับคนนับล้านเยาะเย้ยนิด ๆ หน่อย ๆ แต่ถึงแม้ว่าคุณจะปัดเศษเซ็นต์ต้องจ่ายดอกเบี้ยในบัญชีธนาคาร 10 ล้านจะเสียค่าใช้จ่ายธนาคารมากถ้าครึ่งเซ็นต์ทั้งหมดถูกปัดเศษขึ้นหรือจะต้องเสียลูกค้ามากถ้าทั้งหมด ครึ่งเซ็นต์ถูกปัดเศษลง ดังนั้นฉันสามารถจินตนาการได้ว่านี่เป็นมาตรฐานที่ตกลงกันไว้ ไม่แน่ใจว่าสิ่งนี้ถูกใช้โดยธนาคารจริงๆหรือไม่ ลูกค้าส่วนใหญ่จะไม่สังเกตเห็นการปัดเศษในขณะที่นำเงินมาเป็นจำนวนมาก แต่ฉันสามารถจินตนาการได้ว่านี่เป็นหน้าที่ของกฎหมายหากคุณอาศัยอยู่ในประเทศที่มีกฎหมายที่เป็นมิตรกับลูกค้า
Harald Coppoolse

15

จาก MSDN:

โดยค่าเริ่มต้น Math.Round ใช้ MidpointRounding.ToEven คนส่วนใหญ่ไม่คุ้นเคยกับ "การปัดเศษถึง" เป็นทางเลือก "การปัดเศษออกจากศูนย์" เป็นวิธีที่ใช้กันทั่วไปในโรงเรียน .NET มีค่าเริ่มต้นเป็น "การปัดเศษเป็นคู่" เนื่องจากเป็นสถิติที่เหนือกว่าเพราะไม่ได้แบ่งปันแนวโน้มของ "การปัดเศษออกจากศูนย์" เพื่อปัดเศษขึ้นบ่อยกว่าการปัดเศษลงเล็กน้อย (สมมติว่าตัวเลขที่ปัดเศษมีแนวโน้มที่จะเป็นบวก )

http://msdn.microsoft.com/en-us/library/system.math.round.aspx


3

เนื่องจาก Silverlight ไม่สนับสนุนตัวเลือก MidpointRounding คุณต้องเขียนด้วยตัวคุณเอง สิ่งที่ต้องการ:

public double RoundCorrect(double d, int decimals)
{
    double multiplier = Math.Pow(10, decimals);

    if (d < 0)
        multiplier *= -1;

    return Math.Floor((d * multiplier) + 0.5) / multiplier;

}

สำหรับตัวอย่างรวมถึงวิธีการใช้สิ่งนี้เป็นส่วนขยายให้ดูโพสต์: . NET และการปัดเศษ Silverlight


3

ฉันมีปัญหานี้ที่เซิร์ฟเวอร์ SQL ของฉันปัดขึ้น 0.5 ต่อ 1 ในขณะที่แอปพลิเคชัน C # ของฉันไม่ทำงาน ดังนั้นคุณจะเห็นผลลัพธ์ที่แตกต่างกันสองแบบ

นี่คือการใช้งานกับ int / long นี่คือวิธีที่ Java รอบ

int roundedNumber = (int)Math.Floor(d + 0.5);

มันอาจเป็นวิธีที่มีประสิทธิภาพที่สุดที่คุณคิดเช่นกัน

ถ้าคุณต้องการให้มันเป็นสองเท่าและใช้ความแม่นยำทศนิยมมันเป็นเรื่องของการใช้เลขชี้กำลัง 10 ซึ่งขึ้นอยู่กับจำนวนทศนิยม

public double getRounding(double number, int decimalPoints)
{
    double decimalPowerOfTen = Math.Pow(10, decimalPoints);
    return Math.Floor(number * decimalPowerOfTen + 0.5)/ decimalPowerOfTen;
}

คุณสามารถป้อนทศนิยมลบสำหรับจุดทศนิยมและมันก็เป็นคำที่ดี

getRounding(239, -2) = 200


0

โพสต์นี้มีคำตอบที่คุณต้องการ:

http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx

นี่คือสิ่งที่มันบอกว่า:

ส่งคืนค่า

จำนวนค่าที่ใกล้เคียงที่สุดที่มีความแม่นยำเท่ากับตัวเลข หากค่าอยู่ครึ่งทางระหว่างสองตัวเลขหนึ่งในนั้นคือคู่และคี่อื่น ๆ ดังนั้นจำนวนคู่จะถูกส่งกลับ หากความแม่นยำของค่าน้อยกว่าตัวเลขดังนั้นค่าจะถูกส่งคืนไม่เปลี่ยนแปลง

พฤติกรรมของวิธีการนี้เป็นไปตามมาตรฐาน IEEE 754 ส่วนที่ 4 การปัดเศษนี้บางครั้งเรียกว่าการปัดเศษเป็นใกล้ที่สุดหรือปัดเศษของนายธนาคาร หากตัวเลขเป็นศูนย์การปัดเศษชนิดนี้บางครั้งเรียกว่าการปัดเศษเป็นศูนย์


0

Silverlight ไม่สนับสนุนตัวเลือก MidpointRounding นี่คือวิธีการขยายสำหรับ Silverlight ที่เพิ่มการ MidpointRounding enum:

public enum MidpointRounding
{
    ToEven,
    AwayFromZero
}

public static class DecimalExtensions
{
    public static decimal Round(this decimal d, MidpointRounding mode)
    {
        return d.Round(0, mode);
    }

    /// <summary>
    /// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
    /// </summary>
    /// <param name="d">A Decimal number to be rounded.</param>
    /// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
    /// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
    public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
    {
        if ( mode == MidpointRounding.ToEven )
        {
            return decimal.Round(d, decimals);
        }
        else
        {
            decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
            int sign = Math.Sign(d);
            return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
        }
    }
}

ที่มา: http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/


-1

ใช้การปัดเศษที่กำหนดเอง

public int Round(double value)
{
    double decimalpoints = Math.Abs(value - Math.Floor(value));
    if (decimalpoints > 0.5)
        return (int)Math.Round(value);
    else
        return (int)Math.Floor(value);
}

>.5Math.Roundก่อให้เกิดพฤติกรรมเช่นเดียวกับ คำถามคือ whas 0.5ส่วนหนึ่งที่เกิดขึ้นเมื่อทศนิยมตรง Math.Round อนุญาตให้คุณระบุชนิดของอัลกอริทึมการปัดเศษที่คุณต้องการ
Panagiotis Kanavos

-2

นี่เป็นสิ่งที่น่าเกลียดเหมือนนรกทั้งหมด แต่มักจะทำการปัดเศษเลขคณิตที่ถูกต้องเสมอ

public double ArithRound(double number,int places){

  string numberFormat = "###.";

  numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');

  return double.Parse(number.ToString(numberFormat));

}

5
ดังนั้นการโทรMath.Roundและการระบุว่าคุณต้องการให้รอบ
ปรับแต่งค่าเงิน

-2

นี่คือวิธีที่ฉันต้องแก้ไข:

Public Function Round(number As Double, dec As Integer) As Double
    Dim decimalPowerOfTen = Math.Pow(10, dec)
    If CInt(number * decimalPowerOfTen) = Math.Round(number * decimalPowerOfTen, 2) Then
        Return Math.Round(number, 2, MidpointRounding.AwayFromZero)
    Else
        Return CInt(number * decimalPowerOfTen + 0.5) / 100
    End If
End Function

การลองด้วย 1.905 กับ 2 ทศนิยมจะให้ 1.91 ตามที่คาดไว้ แต่Math.Round(1.905,2,MidpointRounding.AwayFromZero)ให้ 1.90! วิธีการ Math.Round นั้นไม่สอดคล้องกันและใช้ไม่ได้กับปัญหาพื้นฐานส่วนใหญ่ที่โปรแกรมเมอร์อาจประสบ ฉันต้องตรวจสอบว่า (int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2)สาเหตุที่ฉันไม่ต้องการที่จะปัดเศษสิ่งที่ควรจะเป็นรอบลง


Math.Round(1.905,2,MidpointRounding.AwayFromZero)ผลตอบแทน1.91
Panagiotis Kanavos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.