เหตุใด% f จึงพิมพ์ค่าขนาดใหญ่เมื่อค่าคงที่จุดลอยตัวถูกส่งผ่านแทนที่จะเป็นตัวแปร


9

ในโปรแกรมที่กำหนดไม่ฉันได้รับผลลัพธ์ที่แตกต่างกันสำหรับแต่ละเหตุผลprintfหรือไม่?

#include <stdio.h>
int main()
{
    float c = 4.4e10;
    printf("%f\n", c);
    printf("%f\n", 4.4e10);
    return 0;
}

และมันแสดงเอาท์พุทต่อไปนี้:

44000002048.000000
44000000000.000000

4
คำตอบเพื่อให้ห่างไกลอธิบายว่า4.4e10เป็นdoubleค่าคงที่ซึ่งจะถูกแปลงเป็นfloatในการเริ่มต้นของcแต่เก็บไว้เป็นเมื่อผ่านไปdouble printfแต่คุณอาจจะยังต้องการที่จะรู้ว่าการเพิ่มfคำต่อท้ายทำให้มันเป็นfloatค่าคงที่พิมพ์4.4e10fจะแสดงค่าเดียวกันที่เป็นผลมาจากการเริ่มต้นที่จะc ค่าคงที่ที่4.4e10fแยกfloatออกจากdoubleค่าคงที่นั้นมีความสำคัญต่อการทำงานที่มีคุณภาพด้วยเลขคณิตทศนิยม
Eric Postpischil

วิธีการแปลงนี้ตั้งชื่ออะไรหรือไม่? ฉันต้องการอ่านเกี่ยวกับเรื่องนี้
user10056563

คุณต้องการที่จะรู้ว่าการแปลงจากเมื่อdoubleจะfloatเกิดขึ้นในภาษา C หรือไม่? หรือคุณต้องการที่จะรู้ว่าค่าที่เป็นผลมาจากการแปลงนั่นคือสิ่งที่มีผลต่อการแปลง? หรืออย่างอื่น?
Eric Postpischil

ผมตั้งคำถามค่าการตอบกลับที่นี่มิได้มาตรฐาน แต่เมื่อผมยังเด็กและการเรียนรู้Cที่เราใช้printf("%f",x)สำหรับfloatและสำหรับprintf("%lf",x) doubleเมื่อไหร่ที่สิ่งต่าง ๆ เปลี่ยนไป? และหนึ่งจะพิมพ์อย่างชัดเจนอย่างไร (เดี่ยว) float- printf("%hf",x)?
Adrian Mole

2
@Adrian %lfใน printf %fเป็นสิ่งเดียวกับ floatในอาร์กิวเมนต์ตัวแปรจะถูกแปลงเป็นdoubleคอมไพเลอร์เช่นเดียวกับที่ได้รับการดัดแปลงให้เป็นshort int
SS Anne

คำตอบ:


9

A floatเป็นประเภทที่มีหมายเลขจุดลอยตัว 32 บิตในขณะที่ค่าคงที่4.4e10หมายถึงdoubleซึ่งถือหมายเลขจุดลอยตัว 64 บิต (เช่นหมายเลขจุดลอยตัวความแม่นยำสองเท่า )

เมื่อคุณกำหนด4.4e10ให้cค่า4.4e10จะไม่สามารถแสดงได้อย่างแม่นยำ (ข้อผิดพลาดในการปัดเศษในพารามิเตอร์ที่เรียกว่า mantissa) และค่าที่เป็นไปได้ที่ใกล้เคียงที่สุด (44000002048) จะถูกเก็บไว้ เมื่อมันถูกส่งไปยังprintfมันจะเลื่อนกลับไปdoubleรวมถึงข้อผิดพลาดในการปัดเศษ

ในกรณีที่สองค่าเป็นdoubleเวลาทั้งหมดโดยไม่ จำกัด และขยับขยายและมันก็เป็นกรณีที่ a doubleสามารถแทนค่าได้อย่างแน่นอน

หากสิ่งนี้เป็นพฤติกรรมที่ไม่พึงประสงค์คุณสามารถประกาศcว่ามีdoubleความแม่นยำมากขึ้นอีกเล็กน้อย (แต่ระวังว่าคุณจะยังคงมีข้อ จำกัด ด้านความแม่นยำในที่สุด)


3

คุณกำลังพิมพ์ค่าของสองประเภทที่แตกต่างกันที่นี่

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

ในกรณีที่สองคุณผ่านอย่างต่อเนื่องซึ่งมีประเภท4.4e10 doubleประเภทนี้มีความแม่นยำประมาณ 16 หลักทศนิยมและค่าอยู่ในช่วงนั้นดังนั้นค่าที่แน่นอนจะถูกพิมพ์


ทำไมมันถึงพิมพ์ 2048 ในตอนท้าย?
user10056563

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