การเปรียบเทียบความเท่าเทียมกันของจำนวนลอยเข้าใจผิดนักพัฒนารุ่นน้องแม้ว่าจะไม่มีข้อผิดพลาดในการปัดเศษในกรณีของฉันหรือไม่?


31

ตัวอย่างเช่นฉันต้องการแสดงรายการปุ่มจาก 0,0.5, ... 5 ซึ่งข้ามไปแต่ละ 0.5 ฉันใช้สำหรับการวนรอบเพื่อทำเช่นนั้นและมีสีที่แตกต่างกันที่ปุ่ม STANDARD_LINE:

var MAX=5.0;
var DIFF=0.5
var STANDARD_LINE=1.5;

for(var i=0;i<=MAX;i=i+DIFF){
    button.text=i+'';
    if(i==STANDARD_LINE){
      button.color='red';
    }
}

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

var MAX=10;
var STANDARD_LINE=3;

for(var i=0;i<=MAX;i++){
    button.text=i/2.0+'';
    if(i==STANDARD_LINE/2.0){
      button.color='red';
    }
}

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

https://stackoverflow.com/questions/33646148/is-hardcode-float-precise-if-it-can-be-represented-by-binary-format-in-ieee-754

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


23
พฤติกรรมของรายการรหัสสองรายการนี้ไม่เทียบเท่ากัน 3 / 2.0 คือ 1.5 แต่iจะเป็นทั้งจำนวนในรายการที่สองเท่านั้น /2.0ลองเอาสอง
candied_orange

27
หากคุณจำเป็นต้องเปรียบเทียบ FP สองตัวเพื่อความเท่าเทียมกัน (ซึ่งไม่จำเป็นต้องเป็นอย่างที่คนอื่น ๆ ระบุไว้ในคำตอบที่ดีเพราะคุณสามารถใช้การเปรียบเทียบลูปเคาน์เตอร์กับจำนวนเต็ม) แต่ถ้าคุณทำแล้วความคิดเห็นควรเพียงพอ โดยส่วนตัวฉันทำงานกับ IEEE FP มาเป็นเวลานานและฉันยังคงสับสนถ้าฉันเห็นพูดการเปรียบเทียบค่า SPFP โดยตรงโดยไม่แสดงความคิดเห็นหรืออะไรก็ตาม มันเป็นรหัสที่ละเอียดอ่อนมาก - ควรให้ความเห็นอย่างน้อยทุกครั้งที่ IMHO

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

9
เขียนรหัสนั้น จนกว่าจะมีคนคิดว่า 0.6 จะเป็นขนาดขั้นตอนที่ดีกว่าและเพียงแค่เปลี่ยนค่าคงที่
tofro

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

คำตอบ:


116

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

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


48
ฉันชอบ "ข้อบกพร่องที่รอให้เกิดขึ้น" แน่นอนว่ามันอาจใช้งานได้ในขณะนี้แต่สายลมเบา ๆ จากใครบางคนกำลังเดินผ่านจะทำให้แตก
AakashM

10
ตัวอย่างเช่นสมมติว่าข้อกำหนดมีการเปลี่ยนแปลงดังนั้นแทนที่จะเป็น 11 ปุ่มเว้นระยะเท่ากันจาก 0 ถึง 5 ด้วย "บรรทัดมาตรฐาน" บนปุ่มที่ 4 คุณมีปุ่มเว้นระยะเท่ากัน 16 ปุ่มจาก 0 ถึง 5 ด้วย "บรรทัดมาตรฐาน" ในวันที่ 6 ปุ่ม. ดังนั้นใครก็ตามที่รับรหัสนี้จากคุณเปลี่ยน 0.5 เป็น 1.0 / 3.0 และเปลี่ยน 1.5 เป็น 5.0 / 3.0 จะเกิดอะไรขึ้น?
David K

8
ใช่ฉันรู้สึกไม่สบายใจกับความคิดที่ว่าการเปลี่ยนแปลงสิ่งที่ดูเหมือนว่าจะเป็นจำนวนโดยพลการ (เป็น "ปกติ" เป็นจำนวนได้) ไปยังอีกจำนวนหนึ่งโดยพลการ (ซึ่งดูเหมือนว่า "ปกติ" เท่ากัน) แนะนำข้อบกพร่อง
Alexander - Reinstate Monica

7
@Alexander: DIFF must be an exactly-representable double that evenly divides STANDARD_LINEขวาคุณจะต้องแสดงความคิดเห็นที่กล่าวว่า หากคุณไม่ต้องการที่จะเขียนความคิดเห็น (และพึ่งพานักพัฒนาในอนาคตทั้งหมดที่จะรู้มากพอเกี่ยวกับจุดลอยตัวเลขฐานสองของ IEEE754 เพื่อทำความเข้าใจ) อย่าเขียนรหัสด้วยวิธีนี้ คืออย่าเขียนโค้ดด้วยวิธีนี้ โดยเฉพาะอย่างยิ่งเนื่องจากอาจไม่ได้มีประสิทธิภาพมากขึ้น: การเพิ่ม FP มีเวลาแฝงที่สูงกว่าการเพิ่มจำนวนเต็มและเป็นการพึ่งพาแบบวนรอบ นอกจากนี้คอมไพเลอร์ (แม้กระทั่งคอมไพเลอร์ JIT?) อาจทำได้ดีกว่าในการสร้างลูปด้วยตัวนับจำนวนเต็ม
Peter Cordes

39

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

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

var DIFF=0.5;                           // pixel increment
var MAX=Math.floor(5.0/DIFF);           // 5.0 is max pixel width
var STANDARD_LINE=Math.floor(1.5/DIFF); // 1.5 is pixel width

for(var i=0;i<=MAX;i++){
    button.text=(i*DIFF)+'';
    if(i==STANDARD_LINE){
      button.color='red';
    }
}

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


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

1
@ilkkachu True ความคิดของฉันคือว่าถ้าคุณตั้งค่า 5.0 เป็นจำนวนพิกเซลสูงสุดแล้วจากการปัดเศษคุณควรเลือกที่ด้านล่างของ 5.0 นั้นมากกว่าอีกเล็กน้อย 5.0 จะมีประสิทธิภาพสูงสุด แม้ว่าการปัดเศษอาจจะดีกว่าตามสิ่งที่คุณต้องทำ ไม่ว่าในกรณีใดมันก็สร้างความแตกต่างได้เล็กน้อย
Neil

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

คำอธิบายของคุณจะสมบูรณ์ถูกต้องสำหรับ Java / C ++ / ทับทิม / หลาม / ... แต่ Javascript ไม่ได้มีจำนวนเต็มดังนั้นiและSTANDARD_LINEเพียงลักษณะเช่นจำนวนเต็ม มีการบังคับที่ทุกคนไม่เป็นและDIFF, MAXและSTANDARD_LINEมีทั้งหมดเพียงแค่Numbers Numbers ใช้เป็นจำนวนเต็มควรปลอดภัยด้านล่าง2**53พวกเขายังคงเป็นตัวเลขจุดลอยตัว
Eric Duminil

@EricDuminil ใช่ แต่นี่เป็นครึ่งหนึ่งของมัน อีกครึ่งคือการอ่าน ฉันพูดถึงมันเป็นเหตุผลหลักในการทำเช่นนี้ไม่ใช่เพื่อการเพิ่มประสิทธิภาพ
Neil

20

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

รหัสของคุณ "รู้" ว่าความกว้างของเส้นที่มีนั้นเป็นทวีคูณของ 0.5 จาก 0 ถึง 5.0 อย่างแม่นยำ ควรเป็น? ดูเหมือนว่าเป็นการตัดสินใจของอินเทอร์เฟซผู้ใช้ที่อาจเปลี่ยนแปลงได้ง่าย (เช่นคุณอาจต้องการให้ช่องว่างระหว่างความกว้างที่มีอยู่มีขนาดใหญ่ขึ้นตามความกว้างที่ทำได้ 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0 5.0 หรือบางสิ่ง)

รหัสของคุณ "รู้" ว่าความกว้างของเส้นที่มีอยู่ทั้งหมดมีการแสดง "ดี" ทั้งที่เป็นตัวเลขทศนิยมและทศนิยม นั่นก็ดูเหมือนว่าบางสิ่งที่อาจเปลี่ยนแปลงได้ (คุณอาจต้องการ 0.1, 0.2, 0.3, ... ในบางจุด)

รหัสของคุณ "รู้" ว่าข้อความที่จะใส่ปุ่มนั้นเป็นเพียงสิ่งที่ Javascript เปลี่ยนค่าจุดลอยตัวเหล่านั้นให้เป็น นั่นก็ดูเหมือนว่าบางสิ่งที่อาจมีการเปลี่ยนแปลง (เช่นบางทีบางวันคุณอาจต้องการความกว้างเช่น 1/3 ซึ่งคุณอาจไม่ต้องการแสดงเป็น 0.33333333333333 หรืออะไรก็ได้หรือคุณอาจต้องการเห็น "1.0" แทนที่จะเป็น "1" เพื่อความสอดคล้องกับ "1.5" .)

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

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


8

หนึ่งกลิ่นรหัสคือการใช้ลอยในวงเช่นนั้น

การวนรอบสามารถทำได้หลายวิธี แต่ใน 99.9% ของกรณีที่คุณควรยึดติดกับการเพิ่มขึ้นของ 1 หรือจะมีความสับสนแน่นอนไม่เพียง แต่โดยนักพัฒนารุ่นน้อง


ฉันไม่เห็นด้วยฉันคิดว่าจำนวนเต็มทวีคูณของ 1 จะไม่สับสนในการวนรอบ ฉันไม่คิดว่ารหัสจะมีกลิ่น เศษส่วนเท่านั้น
CodeMonkey

3

ใช่คุณต้องการหลีกเลี่ยงสิ่งนี้

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

ใช้ตัวเลขจุดลอยตัวในตำแหน่งที่เหมาะสมตัวอย่างเช่นเมื่อทำการคำนวณทางคณิตศาสตร์ที่คุณต้องการ (เช่นตรีโกณมิติ, พล็อตกราฟฟังก์ชั่น ฯลฯ ) และระมัดระวังเป็นพิเศษเมื่อทำการดำเนินการแบบอนุกรม ความเท่าเทียมกันหมดไปแล้ว ความรู้เกี่ยวกับชุดตัวเลขเฉพาะใดที่แน่นอนตามมาตรฐาน IEEE นั้นเป็นเรื่องที่คลาดเคลื่อนมากและฉันจะไม่พึ่งพามัน

ในกรณีของคุณจะมีกฎหมาย Murphys มาถึงจุดที่ฝ่ายบริหารต้องการให้คุณไม่มี 0.0, 0.5, 1.0 ... แต่ 0.0, 0.4, 0.8 ... หรืออะไรก็ตาม คุณจะถูกบอร์กในทันทีและโปรแกรมเมอร์รุ่นน้อง (หรือตัวคุณเอง) จะทำการดีบักนานและหนักจนกว่าคุณจะพบปัญหา

ในรหัสเฉพาะของคุณฉันจะมีตัวแปรลูปจำนวนเต็มแน่นอน เพราะมันหมายถึงiปุ่ม th ไม่ใช่หมายเลขที่กำลังทำงานอยู่

และฉันอาจจะเพื่อความชัดเจนเป็นพิเศษไม่ใช่เขียนi/2แต่i*0.5ทำให้ชัดเจนว่าเกิดอะไรขึ้นมากมาย

var BUTTONS=11;
var STANDARD_LINE=3;

for(var i=0; i<BUTTONS; i++) {
    button.text = (i*0.5)+'';
    if (i==STANDARD_LINE) {
      button.color='red';
    }
}

หมายเหตุ:ตามที่ระบุไว้ในความคิดเห็น JavaScript ไม่ได้มีประเภทที่แยกต่างหากสำหรับจำนวนเต็ม แต่จำนวนเต็มถึง 15 หลักรับประกันว่าถูกต้อง / ปลอดภัย (ดูhttps://www.ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer ) ดังนั้นการโต้แย้งเช่นนี้ ("คือมัน สับสนมากขึ้น / เกิดข้อผิดพลาดในการทำงานกับจำนวนเต็มหรือไม่ใช่จำนวนเต็ม ") สิ่งนี้ใกล้เคียงกับการแยกประเภท" จิตวิญญาณ "อย่างเหมาะสม; ในการใช้งานประจำวัน (ลูป, พิกัดหน้าจอ, ดัชนีอาร์เรย์ ฯลฯ ) จะไม่มีความประหลาดใจกับตัวเลขจำนวนเต็มที่แสดงNumberเป็น JavaScript


ฉันจะเปลี่ยนชื่อปุ่มเป็นอย่างอื่น - มี 11 ปุ่มหลังจากทั้งหมดและไม่ใช่ 10 อาจเป็น FIRST_BUTTON = 0, LAST_BUTTON = 10, STANDARD_LINE_BUTTON = 3. นอกจากนั้นใช่แล้วนั่นคือวิธีที่คุณควรทำ
gnasher729

เป็นจริง @EricDuminil และฉันได้เพิ่มเล็กน้อยเกี่ยวกับเรื่องนี้ในคำตอบ ขอขอบคุณ!
AnoE

1

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

function precisionRound(number, precision) {
  let factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}

var maxButtonValue = 5.0;
var buttonSpacing = 0.5;

let countEstimate = precisionRound(maxButtonValue / buttonSpacing, 5);
var buttonCount = Math.floor(countEstimate) + 1;

var highlightPosition = 3;
var highlightColor = 'red';

for (let i=0; i < buttonCount; i++) {
    let buttonValue = i / buttonSpacing;
    button.text = buttonValue.toString();
    if (i == highlightPosition) {
        button.color = highlightColor;
    }
}

อาจเป็นรหัสเพิ่มเติม แต่ก็สามารถอ่านได้และมีประสิทธิภาพยิ่งขึ้น


0

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

var MAX=5.0;
var DIFF=0.5
var STANDARD_LINE=1.5;

for(var i=0; (i*DIFF) < MAX ; i=i+1){
    var val = i * DIFF

    button.text=val+'';

    if(val==STANDARD_LINE){
      button.color='red';
    }
}

-1

การคำนวณเลขทศนิยมนั้นช้าและเลขคณิตเลขจำนวนเต็มเร็วดังนั้นเมื่อฉันใช้เลขทศนิยมฉันจะไม่ใช้โดยไม่จำเป็นซึ่งสามารถใช้จำนวนเต็มได้ มันจะมีประโยชน์ในการคิดถึงตัวเลขจุดลอยตัวค่าคงที่เป็นค่าประมาณโดยมีข้อผิดพลาดเล็กน้อย มันมีประโยชน์มากในระหว่างการดีบั๊กเพื่อแทนที่หมายเลขจุดกำเนิดดั้งเดิมด้วยวัตถุบวก / ลบซึ่งคุณถือว่าแต่ละหมายเลขเป็นช่วงแทนที่จะเป็นจุด วิธีนี้ทำให้คุณค้นพบความไม่ถูกต้องที่เพิ่มขึ้นหลังจากการดำเนินการทางคณิตศาสตร์แต่ละครั้ง ดังนั้น "1.5" ควรถูกคิดว่าเป็น "ตัวเลขบางส่วนระหว่าง 1.45 ถึง 1.55" และ "1.50" ควรถูกคิดว่าเป็น "ตัวเลขบางส่วนระหว่าง 1.495 ถึง 1.505"


5
ความแตกต่างของประสิทธิภาพระหว่างจำนวนเต็มและลอยเป็นสิ่งสำคัญเมื่อเขียนรหัส C สำหรับไมโครโปรเซสเซอร์ขนาดเล็ก แต่ซีพียู x86 ที่ได้รับมาในปัจจุบันทำจุดลอยตัวอย่างรวดเร็วจนการลงโทษใด ๆ ถูกทับด้วยโสหุ้ยในการใช้ภาษาไดนามิก โดยเฉพาะอย่างยิ่ง Javascript ไม่ได้แสดงถึงทุก ๆตัวเลขว่าเป็นทศนิยมหรือไม่โดยใช้น้ำหนักบรรทุก NaN เมื่อจำเป็น?
leftaroundabout

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

1
@JeroenMostert SSE / AVX มีการดำเนินการ vectorised สำหรับทั้งจำนวนเต็มและลอยและคุณอาจจะสามารถใช้จำนวนเต็มขนาดเล็ก (เพราะไม่มีบิตที่สูญเปล่าบนเลขชี้กำลัง) ดังนั้นในหลักการแล้วมักจะยังบีบประสิทธิภาพออกมาจากรหัสจำนวนเต็มประสิทธิภาพสูง กว่ากับลอย แต่อีกครั้งสิ่งนี้ไม่เกี่ยวข้องกับแอปพลิเคชันส่วนใหญ่และไม่แน่นอนสำหรับคำถามนี้
leftaroundabout

1
@leftaroundabout: แน่นอน ประเด็นของฉันไม่เกี่ยวกับสิ่งใดที่เร็วกว่าแน่นอนในทุกสถานการณ์เพียงแค่ว่า "ฉันรู้ว่า FP ช้าและจำนวนเต็มเร็วดังนั้นฉันจะใช้จำนวนเต็มถ้าเป็นไปได้" ไม่ใช่แรงจูงใจที่ดีแม้แต่ก่อนที่คุณจะจัดการ คำถามว่าสิ่งที่คุณทำต้องการการเพิ่มประสิทธิภาพหรือไม่
Jeroen Mostert
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.