สิ่งที่ไม่แปรเปลี่ยนคืออะไร?


130

คำนี้ดูเหมือนจะถูกนำไปใช้ในหลายบริบท สิ่งที่ดีที่สุดที่ฉันคิดได้คือมันหมายถึงตัวแปรที่ไม่สามารถเปลี่ยนแปลงได้ นั่นไม่ใช่ค่าคงที่ / รอบชิงชนะเลิศ (คุณคือ Java!) มีไว้เพื่ออะไร?


บางทีพวกเขาควรจะเรียกมันว่าไม่ใช่ตัวแปร?
จอห์นนี่

คำตอบ:


189

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

ตัวอย่างเช่นโครงสร้างการค้นหาแบบไบนารีอาจมีค่าคงที่สำหรับทุกโหนดคีย์ของลูกทางซ้ายของโหนดจะน้อยกว่าคีย์ของโหนดเอง ฟังก์ชันแทรกที่เขียนอย่างถูกต้องสำหรับทรีนี้จะคงค่าคงที่นั้นไว้

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


1
ตัวอย่างที่ดีนี้จะดีกว่าถ้ารวมคำตอบของ cero ไว้ในลิงค์ wikipedia
ablarg

2
อายุของผู้ปกครองมากกว่าอายุของบุตรที่ให้กำเนิด บริบทโดยรอบจะเปลี่ยนไป แต่สิ่งที่ไม่แปรเปลี่ยนไม่เคยเปลี่ยนแปลง ตัวอย่างเช่นอาจเป็นครอบครัว Smith ที่มีลูก 2 คน หรืออาจอยู่ในสัตว์เลี้ยงลูกด้วยนมชนิดอื่นก็ได้ บริบทเปลี่ยนไป แต่ค่าคงที่ไม่เปลี่ยนแปลง
truthadjustr

1
"... คุณสมบัติของสถานะโปรแกรมที่เป็นจริงเสมอ ... " - @jacob baskin - เขียนได้ดีและขอบคุณสำหรับสิ่งนี้
twknab

"... คุณสมบัติของสถานะโปรแกรมที่เป็นจริงเสมอ ... " - ฉันยอมรับว่าเขียนได้ดี แต่อาจทำให้เข้าใจผิดได้ ก่อนอื่นฉันเข้าใจว่ามันเป็นบูลีนจริง แต่ฉันค่อนข้างมั่นใจว่ามันหมายความว่า "... เป็นค่าคงที่เสมอ" (แต่อาจเป็นเพราะภาษาอังกฤษไม่ใช่ภาษาแรกของฉัน)
dev-null

29

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


17

ฉันมักจะดูพวกเขามากกว่าในแง่ของอัลกอริทึมหรือโครงสร้าง

ตัวอย่างเช่นคุณอาจมีค่าคงที่ของลูปที่สามารถยืนยันได้ - เป็นจริงเสมอที่จุดเริ่มต้นหรือจุดสิ้นสุดของการวนซ้ำแต่ละครั้ง นั่นคือถ้าลูปของคุณควรจะประมวลผลกลุ่มของวัตถุจากกองหนึ่งไปยังอีกกองหนึ่งคุณสามารถพูดได้ว่า | stack1 | + | stack2 | = c ที่ด้านบนหรือด้านล่างของวง

หากการตรวจสอบค่าคงที่ล้มเหลวแสดงว่ามีบางอย่างผิดปกติ ในตัวอย่างนี้อาจหมายความว่าคุณลืมดันองค์ประกอบที่ประมวลผลไปยังสแต็กสุดท้ายเป็นต้น


17

ความมหัศจรรย์ของวิกิพีเดีย: Invariant (วิทยาการคอมพิวเตอร์)

ในวิทยาการคอมพิวเตอร์เพรดิเคตที่ถ้าเป็นจริงจะยังคงเป็นจริงตลอดลำดับการดำเนินการที่เฉพาะเจาะจงเรียกว่า (an) ไม่แปรผันกับลำดับนั้น


2
การเชื่อมโยง? ศัพท์แสงทางเทคนิค? อ่าน? WTF ? ;) อย่างจริงจังลิงค์ที่ดี แต่สรุปเล็กน้อยก็น่าจะดี
Dustman

10

ตามที่บรรทัดนี้ระบุ:

ในวิทยาการคอมพิวเตอร์เพรดิเคตที่ถ้าเป็นจริงจะยังคงเป็นจริงตลอดลำดับการดำเนินการที่เฉพาะเจาะจงเรียกว่า (an) ไม่แปรผันกับลำดับนั้น

เพื่อให้เข้าใจได้ดีขึ้นหวังว่าตัวอย่างนี้ใน C ++ จะช่วยได้

พิจารณาสถานการณ์ที่คุณต้องได้รับค่าบางค่าและรับจำนวนรวมของตัวแปรที่เรียกว่าเป็นcountและเพิ่มในตัวแปรที่เรียกว่าsum

คงที่ (อีกครั้งมันมากขึ้นเช่นแนวคิด):

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

โค้ดด้านบนจะเป็นแบบนี้

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}

โค้ดด้านบนทำอะไร?

1) อ่านอินพุตจากcinและใส่เข้าไปx

2) หลังจากการอ่านสำเร็จหนึ่งครั้งการเพิ่มcountและsum = sum + x

3) ทำซ้ำ 1-2 จนกระทั่งหยุดอ่าน (เช่น ctrl + D)

ลูปไม่แปรผัน:

คงที่ต้องเป็น True เสมอ ในตอนแรกคุณเริ่มต้นรหัสของคุณด้วยสิ่งนี้

while(cin>>x){
  }

ลูปนี้อ่านข้อมูลจากอินพุตมาตรฐานและเก็บใน x ดีและดี แต่ค่าคงที่กลายเป็นเท็จเพราะส่วนแรกของค่าคงที่ของเราไม่ได้ตาม (หรือเก็บไว้เป็นจริง)

// we have read count grades so far, and

จะรักษาค่าคงที่เป็นจริงได้อย่างไร?

! ง่าย จำนวนที่เพิ่มขึ้น

ดังนั้น++count;จะทำดี !. ตอนนี้รหัสของเรากลายเป็นแบบนี้

while(cin>>x){
 ++count; 
 }

แต่

ถึงแม้ตอนนี้ค่าคงที่ของเรา(แนวคิดที่ต้องเป็นจริง) ก็เป็นเท็จเพราะตอนนี้เราไม่ตอบสนองส่วนที่สองของค่าคงที่ของเรา

// sum is the sum of the first count grades

แล้วจะทำยังไงดีล่ะ?

เพิ่มxไปsumและเก็บไว้ในsum( sum+=x) และครั้งต่อไปที่ cin>>xจะอ่านค่าใหม่เข้าไป x

ตอนนี้รหัสของเรากลายเป็นแบบนี้

while(cin>>x){
 ++count; 
 sum+=x;
 }

มาตรวจสอบกัน

รหัสตรงกับค่าคงที่ของเราหรือไม่

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

รหัส:

while(cin>>x){
 ++count; 
 sum+=x;
 }

อา!. ตอนนี้ค่าคงที่ของลูปเป็น True เสมอและโค้ดก็ใช้ได้

ตัวอย่างข้างต้นนำมาและแก้ไขจากหนังสือAccelerated C ++โดย Andrew-koening และ Barbara-E



2

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


2

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


2

คำตอบนี้สำหรับเด็กอายุ 5 ขวบของฉัน อย่าคิดว่าค่าคงที่เป็นค่าคงที่หรือค่าตัวเลขคงที่ แต่ก็สามารถทำได้ อย่างไรก็ตามมันมีมากกว่านั้น

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

ค่าคงที่ยังสามารถเป็นค่าคงที่เป็นตัวเลขได้ ตัวอย่างเช่นค่าของpiคืออัตราส่วนที่ไม่แปรเปลี่ยนระหว่างเส้นรอบวงของวงกลมกับเส้นผ่านศูนย์กลาง piไม่ว่าเล็กหรือใหญ่วงกลมคือไม่มีอัตราส่วนที่มักจะเป็น


1

ADT ไม่แปรเปลี่ยนระบุความสัมพันธ์ระหว่างฟิลด์ข้อมูล (ตัวแปรอินสแตนซ์) ที่ต้องเป็นจริงก่อนและหลังการดำเนินการของวิธีอินสแตนซ์ใด ๆ


0

มีตัวอย่างที่ดีของค่าคงที่และทำไมมันเป็นเรื่องสำคัญในหนังสือJava Concurrency ในการปฏิบัติ

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

ใส่คำอธิบายภาพที่นี่


0

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

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

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

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

เมื่อค่าคงที่จะใช้ในการสรุปตรรกะวงเรียกว่าคงห่วง สามารถใช้ลูปภายนอกได้ แต่สำหรับลูปนั้นสำคัญมากเพราะคุณมักจะมีความเป็นไปได้มากมายหรือความเป็นไปได้ที่ไม่สิ้นสุด

สังเกตว่าฉันใช้คำว่า "เพรดิเคต" เป็นตรรกะของซอฟต์แวร์คอมพิวเตอร์และไม่ได้พิสูจน์ และนั่นเป็นเพราะในขณะที่ความไม่แปรเปลี่ยนทางคณิตศาสตร์สามารถใช้เป็นหลักฐานได้ แต่ก็ไม่สามารถพิสูจน์ได้ว่าซอฟต์แวร์คอมพิวเตอร์เมื่อเรียกใช้งานจะให้ผลตามที่คาดหวังเนื่องจากซอฟต์แวร์ถูกเรียกใช้งานบนนามธรรมจำนวนมากซึ่งไม่สามารถพิสูจน์ได้ ว่าพวกเขาจะได้รับสิ่งที่คาดหวัง (ลองนึกถึงสิ่งที่เป็นนามธรรมของฮาร์ดแวร์)

ในที่สุดในขณะที่ตรรกะของซอฟต์แวร์ในทางทฤษฎีและอย่างเข้มงวดมีความสำคัญสำหรับแอปพลิเคชันที่มีความสำคัญสูงเช่นการแพทย์และการทหาร ยังคงสามารถใช้ Invariant เพื่อช่วยโปรแกรมเมอร์ทั่วไปเมื่อทำการดีบัก สามารถใช้เพื่อทราบว่าในตำแหน่งใดตำแหน่งหนึ่งโปรแกรมล้มเหลวเนื่องจากล้มเหลวในการรักษาค่าคงที่บางอย่าง - พวกเราหลายคนใช้มันต่อไปโดยไม่ได้คิดถึงมัน

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