⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 faqcat973e.html

📁 this is a mirrored site c-faq. thought might need offline
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN"><!-- This collection of hypertext pages is Copyright 1995-2005 by Steve Summit. --><!-- Content from the book "C Programming FAQs: Frequently Asked Questions" --><!-- (Addison-Wesley, 1995, ISBN 0-201-84519-9) is made available here by --><!-- permission of the author and the publisher as a service to the community. --><!-- It is intended to complement the use of the published text --><!-- and is protected by international copyright laws. --><!-- The on-line content may be accessed freely for personal use --><!-- but may not be published or retransmitted without explicit permission. --><!-- --><!-- this page built Sat Dec 24 21:47:46 2005 by faqproc version 2.7 --><!-- from source file fp.sgml dated Fri Jul  2 23:51:18 2004 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=fp by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:58:18 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>Floating Point</title></head><body bgcolor="#ffffff"><H1>14. Floating Point</H1><a name="printfprec"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/printfprec.html"><!-- qtag -->Question 14.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>When I set a <TT>float</TT> variable to, say, 3.1,why is <TT>printf</TT> printing it as 3.0999999?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Most computers use base 2for floating-point numbersas well as for integers,andjustas for base 10,not all fractions are representable exactly in base 2.It's well-known thatin base 10,a fraction like1/3 = 0.333333...repeatsinfinitely.It turns out thatinbase 2,one tenthisalsoan infinitely-repeating fraction(0.0001100110011...),soexact decimal fractionssuch as 3.1cannot be represented exactly in binary.Depending on how carefullyyour compiler's binary/decimal conversion routines(such as those used by <TT>printf</TT>)have been written,you may see discrepancies whennumbersnot exactly representable in base 2are assigned or read in and then printed(i.e. converted from base 10 to base 2 and back again).<a href="../../fp/fn77.html" rel=subdocument>[footnote]</a>See also question <a href="faqcat973e.html?sec=fp#round">14.6</a>.<hr><hr><hr><a name="fpdecl"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/fpdecl.html"><!-- qtag -->Question 14.2</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm trying to take somesquare roots,and I've simplified the code down to<pre>	main()	{		printf("%f\n", sqrt(144.));	}</pre>but I'mstillgettingcrazy numbers.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Make sure that you have #included <TT>&lt;math.h&gt;</TT>,andcorrectly declared other functions returning <TT>double</TT>.(Anotherlibrary functionto be careful withis <TT>atof</TT>,which is declared in <TT>&lt;stdlib.h&gt;</TT>.)See also questions<a href="faqcatd3c2.html?sec=decl#implfdecl">1.25</a>,<a href="faqcat973e.html?sec=fp#libm">14.3</a>,and<a href="faqcat973e.html?sec=fp#strangefp">14.4a</a>.</p><p>References:CT&amp;P Sec. 4.5 pp. 65-6<hr><hr><hr><a name="libm"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/libm.html"><!-- qtag -->Question 14.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm trying to do some simpletrig,and I am #including <TT>&lt;math.h&gt;</TT>,butthe linker keepscomplainingthat functions like <TT>sin</TT>and <TT>cos</TT>are undefined.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Make sure you're actually linking with the math library.For instance,due to a longstanding bug in Unix and Linux systems,you usually need to use an explicit <TT>-lm</TT>flag,at the<em>end</em>of the command line,when compiling/linking.See also questions<a href="faqcat1067.html?sec=lib#extlibs">13.25</a>,<a href="faqcat1067.html?sec=lib#libsearch">13.26</a>,and<a href="faqcat973e.html?sec=fp#fpdecl">14.2</a>.<hr><hr><hr><a name="strangefp"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/strangefp.html"><!-- qtag -->Question 14.4a</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>My floating-point calculations are acting strangely and giving medifferent answers on different machines.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>First,see question <a href="faqcat973e.html?sec=fp#fpdecl">14.2</a>.</p><p>If the problem isn't that simple,recall thatdigital computersusuallyuse floating-point formats which provide aclose but by no means exact simulation of real number arithmetic.Among other things, the associative and distributivelaws do nothold completely;that is,order of operation may be important,andrepeated addition is not necessarily equivalent to multiplication.Underflow,cumulative precision loss,and other anomalies are often troublesome.</p><p>Don't assume that floating-point results will be exact,and especially don't assume that floating-point values can becompared for equality.(Don't throw haphazard ``fuzz factors'' in, either;see question <a href="faqcat973e.html?sec=fp#fpequal">14.5</a>.)Beware that some machines have more precision availableinfloating-point computation registersthan in <TT>double</TT> values stored in memory,which can leadto floating-point inequalitieswhen it would seem that two values just<em>have</em>to be equal.</p><p>These problems arenoworse for C than they are for any othercomputer language.Certain aspects offloating-pointare usually defined as ``howeverthe processor does them''(see also questions<a href="faqcat7d4b.html?sec=ansi#undef">11.33</a> and<a href="faqcat7d4b.html?sec=ansi#appalled">11.34</a>),otherwise a compiler for a machine without the ``right''model would have to do prohibitively expensive emulations.</p><p>This document cannot begin to list the pitfalls associated with,and workarounds appropriate for, floating-point work.A goodnumericalprogramming text should cover the basics;see also the references below.(Beware, though, that subtle problems can occupy numerical analysts foryears.)</p><p>References:Kernighan and Plauger,<I>The Elements of Programming Style</I> Sec. 6 pp. 115-8<br>Knuth, Volume 2 chapter 4<br>David Goldberg,``What Every Computer Scientist Should Knowabout Floating-Point Arithmetic''<hr><hr><hr><a name="degrees"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/degrees.html"><!-- qtag -->Question 14.4b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm sure I've got thetrig functionsdeclared correctly,but they're still giving me wrong answers.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You weren't handing them angles in degrees, were you?C's trig functions (like FORTRAN's and most other languages)accept angles in radians.The conversion from degrees to radians is simple enough:<pre>	sin(degrees * pi / 180)</pre><hr><hr><hr><a name="fpequal"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/fpequal.html"><!-- qtag -->Question 14.5</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's a good way to check for ``close enough''floating-point equality?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Since the absolute accuracy of floating point values varies,by definition,with their magnitude,thebest wayof comparing two floating point valuesis to use an accuracy thresholdwhich is relativeto the magnitude of the numbers being compared.Rather than<pre>	double a, b;	...	if(a == b)	/* WRONG */</pre>use something like<pre>	#include &lt;math.h&gt;	if(fabs(a - b) &lt;= epsilon * fabs(a))</pre>where<TT>epsilon</TT>is a value chosen to set thedegree of ``closeness''(and where you know that <TT>a</TT> will not be zero).The precise value of <TT>epsilon</TT> may still have to be chosen withcare:its appropriate value may be quite small and related only to themachine's floating-pointprecision,orit may be largerif the numbers being comparedare inherently less accurateor are the results ofa chain of calculationswhichcompoundsaccuracy lossesover several steps.(Also,you may have to make the thresholda function of <TT>b</TT>,or of both <TT>a</TT> and <TT>b</TT>.)</p><p>A decidedly inferior approach,not generally recommended,would be to use an absolute threshold:<pre>	if(fabs(a - b) &lt; 0.001)		/* POOR */</pre>Absolute``fuzz factors''like0.001never seem to workfor very long,however.As the numbersbeing comparedchange,it's likely that twosmallnumbersthat should be taken as differenthappen to be within 0.001 of each other,or that two large numbers,which should have been treated as equal,differ by more than 0.001 .(And,of course,the problems merely shift around,and do not go away,when the fuzz factor is tweaked to 0.005,or 0.0001,or any other absolute number.)</p><p>Doug Gwyn suggestsusingthefollowing``relative difference''function.Itreturns the relative difference of two real numbers:0.0 if they are exactly the same,otherwise the ratio of the difference to the larger of the two.<pre>#define Abs(x)    ((x) &lt; 0 ? -(x) : (x))#define Max(a, b) ((a) &gt; (b) ? (a) : (b))double RelDif(double a, double b){	double c = Abs(a);	double d = Abs(b);	d = Max(c, d);	return d == 0.0 ? 0.0 : Abs(a - b) / d;}</pre>Typical usage is<pre>	if(RelDif(a, b) &lt;= TOLERANCE) ...</pre></p><p>References:Knuth Sec. 4.2.2 pp. 217-8<hr><hr><hr><a name="round"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../fp/round.html"><!-- qtag -->Question 14.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How do I round numbers?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The simplestand most straightforwardway is with code like<pre>(int)(x + 0.5)</pre>C's floating to integer conversiontruncates (discards) the fractional part,so adding 0.5 before truncatingarranges that fractions&gt;=0.5 will be rounded up.(Thistechnique won't work properly for negative numbers,though,forwhich you could use something like<TT>(int)(x&nbsp;&lt;&nbsp;0&nbsp;?&nbsp;x&nbsp;-&nbsp;0.5&nbsp;:&nbsp;x&nbsp;+&nbsp;0.5)</TT>,or play around with the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -