{"id":90,"date":"2020-11-25T11:28:48","date_gmt":"2020-11-25T11:28:48","guid":{"rendered":"http:\/\/laserphotonics.uk\/?p=90"},"modified":"2020-11-25T12:04:49","modified_gmt":"2020-11-25T12:04:49","slug":"floating-point-precision-in-fortran","status":"publish","type":"post","link":"https:\/\/laserphotonics.uk\/?p=90","title":{"rendered":"FLOATING-POINT PRECISION IN FORTRAN"},"content":{"rendered":"\n<p>Fortran is a numeric beast, which is exactly why its still popular amongst scientific programmers. Languages like C are still somewhat constrained when it comes to numerical precision. In C, a long double gets you\u2026<\/p>\n\n\n\n<p>Fortran 90 and beyond provides a&nbsp;<strong>kind<\/strong>&nbsp;parameter which can be used to specify precision of both reals and integers. Fortran uses the function&nbsp;<strong>selected_real_kind()<\/strong>&nbsp;to create a parameter of real type for&nbsp;<strong>kind.<\/strong>&nbsp;Inputs to this are&nbsp;<em>precision<\/em>&nbsp;and&nbsp;<em>range<\/em>. Here is an example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">integer, parameter :: dp = selected_real_kind(15, 307)\nreal (kind=dp) :: x, y<\/pre>\n\n\n\n<p>This produces a parameter,&nbsp;dp, used to define a double precision real with 15 significant digits, and an exponent range or 307. Single and quad precision can also be defined in a similar way:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">integer, parameter :: sp = selected_real_kind(6, 37)\ninteger, parameter :: qp = selected_real_kind(33, 4931)<\/pre>\n\n\n\n<p>In Fortran 2008, the constants&nbsp;<strong>real32<\/strong>,&nbsp;<strong>real64<\/strong>, and&nbsp;<strong>real128<\/strong>&nbsp;can be used instead of selected_real_kind(). How does this work? Consider the following piece of Fortran code to calculate the repeating decimal 1.0\/7.0. The answer should be 0.142857 142857\u2026 Note that the floating point numbers used have to be tagged as a specific kind (e.g. 1.0<strong>_dp<\/strong>), otherwise the outcome can be erroneous.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">integer, parameter :: dp = selected_real_kind(15, 307)\nreal (kind=dp) :: d\nd = 1.0_dp \/ 7.0_dp<\/pre>\n\n\n\n<p>What happens when we run it &nbsp;in all three precisions?<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&nbsp;  SP = <strong>0.142857<\/strong><span style=\"text-decoration: underline;\">14<\/span>924335479736328125000000000\n   DP = <strong>0.142857142857142<\/strong><span style=\"text-decoration: underline;\">8<\/span>4921269268124888185\n   QP = <strong>0.142857142857142857142857142857142<\/strong><span style=\"text-decoration: underline;\">85<\/span><\/pre>\n\n\n\n<p>The&nbsp;<strong>BOLD <\/strong>numbers show the precision of the number, with correct digits. The&nbsp;Underline numbers are those correct beyond the precision. Now compare this to C\u2019s&nbsp;<strong>long double<\/strong>&nbsp;which is typically 80-bit extended precision. Here\u2019s the C code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">long double d;\nd = 1.0L \/ 7.0L;<\/pre>\n\n\n\n<p>Here\u2019s the result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>0.14285714285714285714<\/strong>09210675491330277964<\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fortran is a numeric beast, which is exactly why its still popular amongst scientific programmers. Languages like C are still somewhat constrained when it comes to numerical precision. In C, a long double gets you\u2026 Fortran 90 and beyond provides a&nbsp;kind&nbsp;parameter which can be used to specify precision of both reals and integers. Fortran uses [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/90"}],"collection":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=90"}],"version-history":[{"count":2,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/90\/revisions"}],"predecessor-version":[{"id":93,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/90\/revisions\/93"}],"wp:attachment":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=90"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=90"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=90"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}