ไม่สามารถใช้โมดูลัสกับคู่ผสมได้หรือไม่


185

ฉันมีโปรแกรมใน C ++ (เรียบเรียงโดยใช้ g ++) ฉันพยายามที่จะใช้สองคู่เป็นตัวถูกดำเนินการกับฟังก์ชั่นโมดูลัส แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

ข้อผิดพลาด: ตัวถูกดำเนินการที่ไม่ถูกต้องของประเภท 'double' และ 'double' เป็นไบนารี 'โอเปอเรเตอร์%'

นี่คือรหัส:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}

12
ดังที่ได้กล่าวไว้แล้ว fmod () จัดเตรียมฟังก์ชันที่จำเป็น ตามที่ยังไม่ได้รับการบันทึกสิ่งสำคัญคือการตระหนักว่าข้อผิดพลาดในการปัดเศษในตัวถูกดำเนินการที่สองfmodอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด ตัวอย่างเช่นfmod(1, 0.1);ควรเป็นศูนย์ทางคณิตศาสตร์ แต่ในความเป็นจริงจะมีค่าเกือบ 0.1 ขอบเขตของข้อผิดพลาดขึ้นกับขนาดของความฉลาด ตัวอย่างเช่นfmod(9E14, 0.1);ประเมินเป็นประมาณ 0.05 ซึ่งมาจากมุมมองทางคณิตศาสตร์ที่ผิดธรรมดา
supercat

1
@supercat รายละเอียดเพิ่มเติมจะน่ากลัว ฉันคิดว่ามีความคิดเกี่ยวกับสิ่งที่อยู่เบื้องหลังเพื่อทำให้สิ่งที่คุณพูดนั้นเป็นความจริง แต่มันก็เป็นการดีที่ได้เห็นเหตุผลว่าทำไมสิ่งที่คุณพูดถึงเป็นจริง จะน่าสนใจเพื่อดูว่ามันทำงานอย่างไรเบื้องหลัง (ฉันคิดว่าฉันเข้าใจ แต่อาจผิดได้ง่ายมาก)
RastaJedi

3
ค่าจุดลอยตัวแสดงถึงจำนวนเต็มหรือเศษส่วนของกำลังสองที่แน่นอน ตัวอย่างเช่นค่าจำนวนเต็ม 0.1 ตัวอักษรเท่ากับ 3602879701896397/36028797018963968 (ค่าหลังคือกำลังสอง) fmod(x,0.1)จะหาร x ด้วยเศษส่วนที่แม่นยำนั้นและหาส่วนที่เหลือแทนที่จะหารด้วยค่าตัวเลข "หนึ่งในสิบ"
supercat

คำตอบ:


272

%ผู้ประกอบการเป็นจำนวนเต็ม คุณกำลังมองหาฟังก์ชั่นfmod()

#include <cmath>

int main()
{
    double x = 6.3;
    double y = 2.0;
    double z = std::fmod(x,y);

}

ฉันกำลังเขียนโปรแกรมใน C ++ สำหรับ Qt และ fmod มีข้อผิดพลาดอยู่ที่นั่น ผลลัพธ์ของ fmod (มุม 360) สามารถเป็น 360 (WAT ?!)
พอล

7
@ พอล: นั่นอาจไม่ใช่ข้อผิดพลาด ถ้าangleเป็นพูด359.9999999แล้วทั้งสองangleและมีแนวโน้มที่จะแสดงเป็นfmod(angle, 360) 360(เพิ่ม 9s เพิ่มเติมตามต้องการ) ลองพิมพ์ค่าด้วยความแม่นยำ 50 หลัก
Keith Thompson

@Store QString :: รูปแบบจะถูกปัดเศษ หากเป็นสิ่งสำคัญคุณจะต้องปัดเศษเองหรือตรวจสอบผลลัพธ์สำหรับ "360" และแทนที่ด้วยค่าของคุณเอง
jfh


5

ใช้จากfmod() <cmath>หากคุณไม่ต้องการรวมไฟล์ส่วนหัว C:

template<typename T, typename U>
constexpr double dmod (T x, U mod)
{
    return !mod ? x : x - mod * static_cast<long long>(x / mod);
}

//Usage:
double z = dmod<double, unsigned int>(14.3, 4);
double z = dmod<long, float>(14, 4.6);
//This also works:
double z = dmod(14.7, 0.3);
double z = dmod(14.7, 0);
double z = dmod(0, 0.3f);
double z = dmod(myFirstVariable, someOtherVariable);

3
ทำไมคุณไม่ต้องการรวมไฟล์ส่วนหัว C นั่นคือสิ่งที่มันมีไว้เพื่อ
Keith Thompson

2

คุณสามารถใช้ฟังก์ชั่นโมดูลัสของคุณเองเพื่อทำสิ่งนี้สำหรับคุณ:

double dmod(double x, double y) {
    return x - (int)(x/y) * y;
}

จากนั้นคุณสามารถใช้dmod(6.3, 2)เพื่อรับส่วนที่เหลือ, 0.3.


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