1+ module precision2
2+
3+ // <Snippet8>
4+ open System
5+
6+ let roundApproximate dbl digits margin mode =
7+ let fraction = dbl * Math.Pow( 10 , digits)
8+ let value = Math.Truncate fraction
9+ let fraction = fraction - value
10+ if fraction = 0 then
11+ dbl
12+ else
13+ let tolerance = margin * dbl
14+ // Determine whether this is a midpoint value.
15+ if ( fraction >= 0.5 - tolerance) && ( fraction <= 0.5 + tolerance) then
16+ if mode = MidpointRounding.AwayFromZero then
17+ ( value + 1. ) / Math.Pow( 10 , digits)
18+ elif value % 2. <> 0 then
19+ ( value + 1. ) / Math.Pow( 10 , digits)
20+ else
21+ value / Math.Pow( 10 , digits)
22+ // Any remaining fractional value greater than .5 is not a midpoint value.
23+ elif fraction > 0.5 then
24+ ( value + 1. ) / Math.Pow( 10 , digits)
25+ else
26+ value / Math.Pow( 10 , digits)
27+
28+
29+ let roundValueAndAdd value =
30+ let tolerance = 8e-14
31+ let round = roundApproximate value 0 tolerance
32+
33+ printfn $" {value,5:N1} {value,20:R} {round MidpointRounding.ToEven,12} {round MidpointRounding.AwayFromZero,15}"
34+ value + 0.1
35+
36+ printfn " %5s %20s %12s %15s \n " " Value" " Full Precision" " ToEven" " AwayFromZero"
37+ let mutable value = 11.1
38+ for _ = 0 to 5 do
39+ value <- roundValueAndAdd value
40+
41+ printfn " "
42+
43+ value <- 11.5
44+ roundValueAndAdd value
45+ |> ignore
46+
47+ // The example displays the following output:
48+ // Value Full Precision ToEven AwayFromZero
49+ //
50+ // 11.1 11.1 11 11
51+ // 11.2 11.2 11 11
52+ // 11.3 11.299999999999999 11 11
53+ // 11.4 11.399999999999999 11 11
54+ // 11.5 11.499999999999998 12 12
55+ // 11.6 11.599999999999998 12 12
56+ //
57+ // 11.5 11.5 12 12
58+ // </Snippet8>
0 commit comments