เลขคณิตจุดคงที่บนไมโครคอนโทรลเลอร์


12

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

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

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

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


1
ฉันคิดว่านี่เป็นวิธีที่ดีกว่าสำหรับ stackoverflow เนื่องจากโซลูชันดังกล่าวเป็นแบบทั่วไปและไม่เกี่ยวกับหุ่นยนต์มากนัก
Shahbaz

1
@Jakob - โปรดทราบว่าคำถามเหล่านั้นทั้งสองถูกปิดเป็นไม่สร้างสรรค์
Mark Booth

1
นี่คือสิ่งที่จะทำให้ C ++ มีประโยชน์มากสำหรับระบบฝังตัว เทมเพลตจะสร้างรหัสที่ถูกต้องและเหมาะสมที่สุดโดยอัตโนมัติ
Rocketmagnet

1
ฉันขอดูฟังก์ชั่น atan ของคุณได้ไหม? ฉันกำลังพยายามที่จะแก้ไขปัญหาการแปลงแบบลอยตัวถึงจุดคงที่ในการวิจัยเชิงวิชาการของฉันและฉันยินดีที่จะพูดคุยกับมัน
Joe Hass

1
อะไหล่ @ronalchn ของ Arduino (เป็น AVR ไมโคร) ภาษาจะดำเนินการใน C ++ นอกจากนี้ยังมี++ ห้องสมุด และด้ายที่คอมไพเลอร์นี้จะใช้
embedded.kyle

คำตอบ:


7

มันจะดีถ้าเราบอกคอมไพเลอร์เกี่ยวกับช่วงและความแม่นยำของตัวแปรอินพุต - จุดคงที่แต่ละตัว (อาจไม่มีสองตำแหน่งที่มีจุด radix อยู่ในตำแหน่งเดียวกัน) และมันจะอัตโนมัติ - ในเวลารวบรวม - ใช้ช่วงที่ถูกต้อง และความแม่นยำและการดำเนินการ rescaling สำหรับค่ากลางและค่าสุดท้ายในชุดของการคำนวณ ฉันได้ยินข่าวลือว่าอาจเป็นไปได้ที่จะทำเช่นนั้นในภาษาการเขียนโปรแกรม Adaหรือในเทมเพลต C ++

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


เป็นไปได้ที่จะทำได้โดยใช้เทมเพลต C ++
Rocketmagnet

ฉันกำลังทำอะไรบางอย่างเช่นเดียวกับคุณ "จะดีถ้า ... " ความคิดเห็น มันเป็นปลั๊กอินสำหรับ gcc ที่แปลงรหัส C จุดลอยตัวเป็นจุดคงที่, เพิ่มประสิทธิภาพของตำแหน่งจุดไบนารีทั้งหมดไปพร้อมกัน ฉันมีกระดาษส่งไปยังวารสาร ACM และอื่น ๆ ในการเตรียมการ หากคุณมีรหัส C สำหรับฟังก์ชั่น atan ฉันยินดีที่จะให้มันยิง ... ฉันสามารถให้คุณกลับรหัส C ที่ใช้ตัวแปรจำนวนเต็มและทำทุกสิ่งที่จุดคงที่
Joe Hass

+1 สำหรับคำตอบที่สมบูรณ์มากกว่าคำตอบ ฉันได้แก้ไขลิงก์ในเหมืองเพื่อรวมลิงก์ไปยังสถานที่เพื่อขอซอร์สโค้ดเพื่อแก้ไขความคิดเห็นของ Mark Booth คุณอาจต้องการอัปเดตลิงก์ของคุณเช่นกัน ฉันจะทำเอง แต่การแก้ไขที่แนะนำอยู่ในคิวและบล็อกฉัน
embedded.kyle

1
@Rocketmagnet แน่นอนที่สุดแล้วมันเป็นไปได้ที่จะใช้คะแนนคงที่โดยใช้เทมเพลตดูที่FixedPoints (ข้อจำกัดความรับผิดชอบ: ฉันเขียนสิ่งนี้และมันยังคงอายุน้อยมาก)
Pharap

ลิงก์ gcc "a" เสียหาย
Lesto

2

ฉันใช้ไลบรารี TI IQMathเพื่อใช้จุดลอยตัวเสมือนบน DSP จุดคงที่ของพวกเขา

Texas Instruments TMS320C28x IQmath Library คือชุดของฟังก์ชั่นทางคณิตศาสตร์ที่ปรับให้เหมาะสมและมีความแม่นยำสูงสำหรับโปรแกรมเมอร์ C / C ++ เพื่อต่อเชื่อมอัลกอริธึมจุดลอยตัวเข้ากับรหัสจุดคงที่บนอุปกรณ์ TMS320C28x ได้อย่างราบรื่น โดยทั่วไปแล้วรูทีนเหล่านี้จะใช้ในแอปพลิเคชันแบบเรียลไทม์ซึ่งใช้ความเร็วในการประมวลผลและความแม่นยำสูงเป็นสิ่งสำคัญ โดยใช้งานประจำเหล่านี้คุณสามารถบรรลุความเร็วในการดำเนินการได้เร็วกว่าโค้ดเทียบเท่าที่เขียนในภาษา ANSI C มาตรฐาน นอกจากนี้ด้วยฟังก์ชั่นความแม่นยำสูงที่พร้อมใช้งานห้องสมุด TI IQmath สามารถลดเวลาในการพัฒนาแอปพลิเคชัน DSP ของคุณได้อย่างมาก

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


@downvoter สนใจที่จะแสดงความคิดเห็นในสิ่งที่ผิดกับคำตอบของฉัน?
embedded.kyle

+1: ห้องสมุดนี้ดีกว่าที่เขาใช้อยู่ตอนนี้ ("แค่ใช้จำนวนเต็ม") มันไม่ได้ทำทุกสิ่งที่คำถามดั้งเดิมถาม แต่ฉันคิดว่าคำตอบเช่นนี้ (มีประโยชน์ แต่ไม่ใช่โซลูชันที่สมบูรณ์) ไม่สมควรได้รับ downvote - เว้นแต่จะมีวิธีแก้ปัญหาที่สมบูรณ์จริง ๆ (ซึ่งฉันสงสัยในกรณีนี้ )
David Cary

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

@ MarkBooth ฉันเปลี่ยนลิงค์จากไลบรารี่ C28x เป็นไลบรารี่ C64x หากคุณไปที่ลิงก์ดังกล่าวคุณสามารถขอซอร์สโค้ดได้ คุณต้องมี บริษัท หรืออีเมลของมหาวิทยาลัยเพื่อเข้าถึง ยังคงฟรีเหมือนในเบียร์และการพูด คุณเพียงแค่ต้องยกมือขึ้นและรอให้ได้รับการติดต่อก่อนจึงจะสามารถพูดได้ ค่อนข้างน่ารำคาญ แต่เมื่อคุณมีซอร์สโค้ดมันจะสามารถปรับให้เข้ากับโปรเซสเซอร์ที่คุณชอบ
embedded.kyle

Thanks @ embedded.kyle source code นั้นดีกว่า binary เพียงอย่างเดียว แต่ก็ยังมีการใช้งานเพียงเล็กน้อยถ้าสิทธิ์ใช้งานอนุญาตให้คุณใช้ในแบบ จำกัด เท่านั้น ตามที่หน้าC6x Software Librariesนั้นแหล่งที่มานั้นออกภายใต้ใบอนุญาตการค้าของ TIเท่านั้นซึ่งแทบจะไม่ได้พูดอะไรอย่างแน่นอน
Mark Booth

1

มีการนำไปใช้งานจำนวนมาก (ไม่มีไลบรารีใดที่ฉันรู้ได้ทันที) เกี่ยวกับการปรับขนาดไบนารี (หรือที่เรียกว่าการปรับขนาด B)

ในที่นี้คุณจะต้องจดบันทึก (หรือดียิ่งกว่านั้นคือบันทึกรหัส ... ) ว่ามีจุดทศนิยมอยู่ที่ไหนโดยใช้การเลื่อนเพื่อเลื่อนจุดทศนิยมขึ้นหรือลง

ฉันใช้ B-scaling ในแอสเซมเบลอร์ในโครงการป้องกันแม้กระทั่งซีพียูที่เล็กที่สุดก็สามารถรับรองความเหมาะสมสำหรับสิ่งอื่น ...


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

0

ถ้าคุณใช้จำนวนเต็มจำที่ "จุด" คือพวกเขามีชนิดของการใช้ลอยคำนวณจุด จุดคงที่จริงๆยังคงจุด

ฉันสงสัยว่าสำหรับทุกฟังก์ชั่นจะมี "preprocessing" ที่แตกต่างกันเพื่อทำให้หมายเลข "floating" ของคุณเหมาะสำหรับฟังก์ชั่น ตัวอย่างเช่นสำหรับatanคุณต้องการเปลี่ยนตัวเลขเพื่อให้จุดทศนิยมตรงกับฟังก์ชันจุดคงที่ของคุณ สำหรับcosคุณอาจต้องการได้ในช่วงและแล้วเลื่อนมัน- πππ

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

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

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

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

โดยที่จำนวนทั้งหมดคือinteger.fractionซึ่งมีการใช้หน่วยความจำเท่ากันช่วงของค่าที่สูงกว่าและโดยทั่วไปจะใช้ง่ายกว่า


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

ผมไม่ได้หมายจำในขณะที่เก็บไว้ในตัวแปรที่ผมหมายถึงจำได้ว่าในขณะที่ผมจำได้ว่าวิธีการแปลผล (โดยรู้ที่จุดทศนิยมเป็น)
ronalchn

@ronalchn ฉันเห็น คุณหมายถึงบางสิ่งเช่นกับ#defineใช่มั้ย? ฉันคิดว่าคุณเก็บมันไว้จริงและมันอาจแตกต่างกันไปตามจำนวนของคุณเล็กหรือใหญ่
Shahbaz

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