2017-03-07 73 views
1

爲以下代碼輸入大數字會導致scanf成功,儘管該值未被正確存儲。scanf成功,但存儲的值對於某些大型浮點數不適用

printf("\nDouble max: %f\n", DBL_MAX); 
printf("\nFloat max: %f\n", FLT_MAX); 
printf("\nPlease insert root1 data: "); 
float input1; 
scanResult = scanf("%f", &input1); 
printf("\nScan Result is %d\n", scanResult); 

double input2; 
printf("\nPlease insert root2 data: "); 
scanResult = scanf("%lf", &input2); 
printf("\nScan Result is %d\n", scanResult); 

printf("%f", input1); 
printf("%f", input2); 

輸出:

Double max: 17976931348623157000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 
0.000000 

Float max: 340282346638528860000000000000000000000.000000 

Please insert root1 data: 1872389723948273985723984756982375698374568 

Scan Result is 1 

Please insert root2 data: 928734812348721834.2348275 

Scan Result is 1 


1.#INF00 

928734812348721790.000000 

所以我的問題是:

  1. 首先掃描:爲什麼scanf還是要說的掃描結果爲1,當你可以看到,價值存儲不正確?

  2. 第二次掃描:爲什麼它會舍入它,我該如何解決它?

  3. 一般:我們可以看到,通過0的數量,該​​和FLT_MAX比我給的輸入大得多。那爲什麼它不正確地存儲輸入?

+0

您需要更好的'c'書籍(或網站) – KevinDTimm

+0

@KevinDTimm我可以理解爲什麼嗎? –

+0

對於scanf()有關溢出處理的有趣問題+1。這不僅抵消了你不努力驗證你的輸入;-)。 –

回答

1
  1. 首先掃描:爲什麼scanf還是要說的掃描結果爲1,當你可以看到,值存放不當?

的第一數量大於FLT_MAX大,因此被正確地解析爲無窮大。

  • 第二次掃描:爲什麼會這樣四捨五入它,以及如何解決 呢?
  • 的第二數量比​​小,所以它找到用於輸入數字的最佳雙精度浮點值。這是顯示的內容。如果你不明白這是什麼意思, this article will help

  • 一般來說:我們可以看到,通過0的數,使得​​和FLT_MAX比我給輸入大得多。那爲什麼它不正確地存儲輸入?
  • 不正確。您正在將較大的數字解析爲雙精度數字,並將較小的數字解析爲精度。

    3
    1. 首先掃描:爲什麼scanf還是要說的掃描結果爲1,當你可以看到,值存放不當?

    掃描結果爲1,因爲一個輸入項被匹配,轉換和分配。這是scanf()的非負值時的返回值的含義。

    此外,我看到值存儲不正確。您提供了一個數字序列,該數字序列被解釋爲一個十進制數字,它大於float可以表示的最大值。 scanf()函數將這些輸入轉換爲float作爲表示系統可以表示的最大「值」的數字;在你的實現中,這是一個float正無限。

  • 第二次掃描:爲什麼會這樣四捨五入它,我怎麼能解決這個問題?
  • 浮點數具有固定大小的表示形式,就像所有C的內置數據類型一樣。因此,它們的精度有限制,並且其範圍內有許多數字不能完全表示。這是浮點和整數之間的折衷:前一類的類型具有更寬的範圍和比例,但它們通常不精確。

    您的機器很可能使用IEEE-754二進制雙精度作爲其格式double。該格式提供15-16個十進制數字的精度。當某些輸入轉換爲double(即使使用不同的表示形式)時,您無法避免舍入,因爲數字格式無法將輸入表示爲其原始精度。通過scanf()讀取輸入而不捨入的唯一方法是將其作爲字符串而不是數字讀取。

  • 一般來說:我們可以看到,通過0的數,使得​​和FLT_MAX比我給輸入大得多。那爲什麼它不正確地存儲輸入?
  • 除了有限精度問題,我已經討論過,也請注意,你的第一個輸入大於FLT_MAX較大,但您嘗試讀取它作爲一個float。如果您認爲輸入在目標數字格式的範圍內,則說明您錯了。

    +0

    良好的信息。我實際上會期望scanf()在溢出的情況下失敗;我發現[man page](http://pubs.opengroup.org/onlinepubs/7908799/xsh/fscanf.html)缺少錯誤條件。對'strtod'的引用只涉及格式,而不是錯誤處理。例如,我可以期待scanf()設置「errno」嗎? –

    +0

    @ PeterA.Schneider,您明確引用的手冊頁說:「如果發生讀取錯誤,則設置流的錯誤指示符,返回」EOF「,並將」errno「設置爲指示錯誤。它也指向'fgetc()'和'fgetwc()'來設置可能的錯誤,並指定一些附加的錯誤。 –

    +0

    @ PeterA.Schneider,請注意,錯誤條件僅爲*讀取錯誤*而明確定義。 'scanf()'在匹配失敗時不報告錯誤。此外,它不能報告超出範圍數字輸入的匹配失敗,因爲如果匹配失敗,則需要將整個不匹配的輸入保留在流中。你不能依賴於能夠推回多個字符,所以到'scanf()'可以檢測到輸入對應於超出範圍的數字時,它就承諾以某種方式轉換*。 –

    相關問題