ฉันจะคำนวณหารและโมดูโลสำหรับจำนวนเต็มใน C # ได้อย่างไร


87

ฉันจะคำนวณการหารและโมดูโลสำหรับตัวเลขจำนวนเต็มใน C # ได้อย่างไร


16
นี่อาจจะธรรมดาเกินไป แต่มันเป็นคำถามที่แท้จริง ...

2
โพสต์ที่เกี่ยวข้องและบล็อกต้องอ่านว่าเหตุใด%ตัวดำเนินการจึงไม่ใช่ตัวดำเนินการโมดูลัสใน C #
RBT

คำตอบ:


124

ก่อนที่จะถามคำถามแบบนี้โปรดตรวจสอบเอกสาร MSDN

เมื่อคุณหารจำนวนเต็มสองจำนวนผลลัพธ์จะเป็นจำนวนเต็มเสมอ ตัวอย่างเช่นผลลัพธ์ของ 7/3 คือ 2 ในการกำหนดส่วนที่เหลือของ 7/3 ให้ใช้ตัวดำเนินการที่เหลือ ( % )

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2

10
% คืนค่าส่วนที่เหลือไม่ใช่โมดูลัส (ตามที่คุณชี้ให้เห็น) ไม่ใช่สิ่งเดียวกันและอาจทำให้เกิดปัญหาเมื่อต้องรับมือกับกรณีที่ผิดปกติ (เช่นดัชนีเชิงลบ) อย่างไรก็ตามสามารถใช้เหมือนกับตัวดำเนินการโมดูลัสเมื่อมองหาเช่นการทำซ้ำทุกๆ 10 ครั้งของตัวทำดัชนีที่เป็นบวกอย่างอ่อน บางทีคุณอาจอธิบายวิธีคำนวณโมดูลัสที่แท้จริงได้?
Cor_Blimey

1
จริงฉันอ่านโพสต์แบบนี้และฉันมีปัญหาในแอปพลิเคชันของฉัน :)
apocalypse

1
... อะไรคือประเด็นของการประกาศaและbถ้าคุณจะไม่ใช้มัน? : D
leviathanbadger

1
บางทีผู้ใช้อาจกำลังค้นหา (เช่นฉัน) สำหรับฟังก์ชัน DivRem ดังนั้นคำถามอาจไม่น่าสนใจเท่าที่คิดในตอนแรก ขอบคุณ @danodonovan
Tancredi

1
คำตอบนั้นไม่ง่ายอย่างที่คำตอบนี้อ้างอย่างที่คนอื่น ๆ ชี้ให้เห็นและอาจนำไปสู่ข้อผิดพลาดที่แก้ไขได้ยาก ดู/programming/10065080/mod-explanation
SansWit

90

นอกจากนี้ยังมี Math.DivRem

quotient = Math.DivRem(dividend, divisor, out remainder);

2
นี่ควรเป็นคำตอบที่ถูกต้องในความคิดของฉันเพราะมันให้ผลหารและส่วนที่เหลือในฟังก์ชันเดียว ฉันไม่แน่ใจว่าแนวทางใดทำงานได้ดีกว่า (ใช้ "a / b" เพื่อหาผลหารแล้ว "a% b" เพื่อรับเศษที่เหลือหรือ Math.DivRem) แต่วิธีนี้ดีกว่าในการอ่านมาก (ในกรณีของฉันฉันต้องการ เพื่อให้ทราบทั้งผลหารและเศษเหลือ) - ขอบคุณ!
Igor

2
@Igor ขอบคุณเมื่อตอบคำถามเดิมฟังก์ชั่นนี้ไม่มีอยู่! อย่างไรก็ตามการมีอยู่ของฟังก์ชั่นทำให้ข้อสังเกตของ as-cii เกี่ยวกับการตรวจสอบเอกสารนั้นดูงี่เง่าเล็กน้อย .... :)
danodonovan

6
เพื่อหลีกเลี่ยงความสับสนMath.DivRemอย่าคำนวณ div และ mod ในการดำเนินการเดียว มันเป็นเพียงฟังก์ชั่นผู้ช่วยและซอร์สโค้ดคือ: public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik

9
@NightElfik การนำไปใช้งานอาจเปลี่ยนแปลงได้ในอนาคตและรันไทม์จะระบุการเรียกใช้เมธอดสำหรับการเพิ่มประสิทธิภาพได้ง่ายกว่าการไม่ปะติดปะต่อdivและremคำแนะนำ
kbolino

6
@kbolino นั่นเป็นคำทำนายที่ดีเนื่องจากมันมีการเปลี่ยนแปลงอย่างน้อยใน .NET หลักในการแบ่งและลบ และมีการวางแผนการเพิ่มประสิทธิภาพเพิ่มเติมใน RyuJIT เพื่อใช้คำสั่ง x86 div เดียวแม้ว่าการเปลี่ยนแปลง JIT ควรตรวจจับ%และ/ตัวดำเนินการหากใช้แยกกัน
Bob

15

ช่วงเวลาสนุก!

การดำเนินการ 'โมดูลัส' ถูกกำหนดให้เป็น:

a % n ==> a - (a/n) * n

อ้างอิง:เลขคณิตโมดูลาร์

ดังนั้นคุณสามารถหมุนของคุณเองได้แม้ว่ามันจะช้ากว่าตัวดำเนินการ% ในตัว:

public static int Mod(int a, int n)
{
    return a - (int)((double)a / n) * n;
}

แก้ไข: ว้าวผิดพลาดค่อนข้างแย่ที่นี่ แต่เดิมขอบคุณ @joren ที่จับฉันได้

ตอนนี้ฉันอาศัยข้อเท็จจริงที่ว่าการหาร + cast-to-int ใน C # เทียบเท่ากับMath.Floor(กล่าวคือลดเศษส่วนลง) แต่การใช้งาน "จริง" จะเป็นดังนี้:

public static int Mod(int a, int n)
{
    return a - (int)Math.Floor((double)a / n) * n;
}

ในความเป็นจริงคุณสามารถเห็นความแตกต่างระหว่าง% และ "โมดูลัสจริง" ได้ดังต่อไปนี้:

var modTest =
    from a in Enumerable.Range(-3, 6)
    from b in Enumerable.Range(-3, 6)
    where b != 0
    let op = (a % b)
    let mod = Mod(a,b)
    let areSame = op == mod
    select new 
    { 
        A = a,
        B = b,
        Operator = op, 
        Mod = mod, 
        Same = areSame
    };
Console.WriteLine("A      B     A%B   Mod(A,B)   Equal?");
Console.WriteLine("-----------------------------------");
foreach (var result in modTest)
{
    Console.WriteLine(
        "{0,-3} | {1,-3} | {2,-5} | {3,-10} | {4,-6}", 
        result.A,
        result.B,
        result.Operator, 
        result.Mod, 
        result.Same);
}

ผล:

A      B     A%B   Mod(A,B)   Equal?
-----------------------------------
-3  | -3  | 0     | 0          | True  
-3  | -2  | -1    | -1         | True  
-3  | -1  | 0     | 0          | True  
-3  | 1   | 0     | 0          | True  
-3  | 2   | -1    | 1          | False 
-2  | -3  | -2    | -2         | True  
-2  | -2  | 0     | 0          | True  
-2  | -1  | 0     | 0          | True  
-2  | 1   | 0     | 0          | True  
-2  | 2   | 0     | 0          | True  
-1  | -3  | -1    | -1         | True  
-1  | -2  | -1    | -1         | True  
-1  | -1  | 0     | 0          | True  
-1  | 1   | 0     | 0          | True  
-1  | 2   | -1    | 1          | False 
0   | -3  | 0     | 0          | True  
0   | -2  | 0     | 0          | True  
0   | -1  | 0     | 0          | True  
0   | 1   | 0     | 0          | True  
0   | 2   | 0     | 0          | True  
1   | -3  | 1     | -2         | False 
1   | -2  | 1     | -1         | False 
1   | -1  | 0     | 0          | True  
1   | 1   | 0     | 0          | True  
1   | 2   | 1     | 1          | True  
2   | -3  | 2     | -1         | False 
2   | -2  | 0     | 0          | True  
2   | -1  | 0     | 0          | True  
2   | 1   | 0     | 0          | True  
2   | 2   | 0     | 0          | True  

"ตอนนี้ฉันอาศัยข้อเท็จจริงที่ว่าการหารจำนวนเต็มใน C # เทียบเท่ากับ Math.Floor (กล่าวคือมันลดเศษส่วนลง)" - แต่มันไม่ใช่ หารจำนวนเต็มจะปัดเศษเป็นศูนย์คณิตศาสตร์รอบชั้นไปทางลบอินฟินิตี้
Joren

@Joren ขออภัย แต่ไม่ - ลองรันสิ่งนี้: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- ทั้งหมด 0
JerKimball

2
ครั้งแรกที่ผมพูดถึงแบ่งจำนวนเต็ม จะเกิดอะไรขึ้นถ้าคุณทำการหารทศนิยมแล้วโยนเป็นจำนวนเต็มไม่เกี่ยวข้อง (แม้ว่าจะให้ผลลัพธ์เดียวกันก็ตาม) อย่างที่สองฉันไม่แน่ใจว่าทำไมคุณถึงคาดหวังว่าจำนวนเต็มระหว่าง 0 ถึง 9 จะให้สิ่งอื่นที่ไม่ใช่ 0 หลังจากหารด้วย 10 และตัดทอนเป็นส่วนจำนวนเต็ม ถ้านั่นส่งผลให้ 1 นั้นจะปัดเศษออกจากศูนย์หรือไปทางอินฟินิตี้บวก ประการที่สามไม่มีความแตกต่างใด ๆระหว่างการปัดเศษไปยังศูนย์และการปัดเศษไปยังค่าอนันต์เชิงลบสำหรับจำนวนบวกดังนั้นคุณจึงไม่ได้ระบุถึงปัญหา
Joren

Math.Floor(-10.0 / 3.0)และ-10 / 3มีไม่ได้ในสิ่งเดียวกัน
Joren

@joren อาฉันเห็นการตัดการเชื่อมต่อที่นี่ - ไม่ฉันไม่ได้ทำการหารจำนวนเต็มฉันทำการหารสองจากนั้นแคสต์ผลลัพธ์เป็นจำนวนเต็ม - แตกต่างกันมาก
JerKimball

14

การหารดำเนินการโดยใช้ตัว/ดำเนินการ:

result = a / b;

การแบ่ง Modulo ทำได้โดยใช้ตัว%ดำเนินการ:

result = a % b;

1
+1: การออกจากประเภทอย่างสะดวกสบายทำให้เป็นคำตอบที่ดีขึ้น :-) ฉันเชื่อว่าสิ่งนี้ใช้ได้กับ System.Numeric.BigInteger ใน 4.0 ด้วย

5
% -> ตามที่ Cor_Blimey กล่าวมันส่งคืนส่วนที่เหลือไม่ใช่โมดูลัส ตัวอย่างเช่น: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com]
คัมภีร์ของศาสนาคริสต์

2
หมายเหตุ: Modulo ไม่เหมือนกับโมดูลัส โมดูโลเป็นส่วนที่เหลือโมดูลัสคือค่าสัมบูรณ์
Ryan

-4

อ่านจำนวนเต็มสองจำนวนจากผู้ใช้ จากนั้นคำนวณ / แสดงส่วนที่เหลือและผลหาร

// When the larger integer is divided by the smaller integer
Console.WriteLine("Enter integer 1 please :");
double a5 = double.Parse(Console.ReadLine());
Console.WriteLine("Enter integer 2 please :");
double b5 = double.Parse(Console.ReadLine());

double div = a5 / b5;
Console.WriteLine(div);

double mod = a5 % b5;
Console.WriteLine(mod);

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