Safe addition: Difference between revisions

Content added Content deleted
(Added Hare)
m (syntax highlighting fixup automation)
Line 28: Line 28:
=={{header|Ada}}==
=={{header|Ada}}==
An interval type based on Float:
An interval type based on Float:
<lang Ada>type Interval is record
<syntaxhighlight lang="ada">type Interval is record
Lower : Float;
Lower : Float;
Upper : Float;
Upper : Float;
end record;</lang>
end record;</syntaxhighlight>
Implementation of safe addition:
Implementation of safe addition:
<lang Ada>function "+" (A, B : Float) return Interval is
<syntaxhighlight lang="ada">function "+" (A, B : Float) return Interval is
Result : constant Float := A + B;
Result : constant Float := A + B;
begin
begin
Line 51: Line 51:
return (Float'Adjacent (0.0, Float'First), Float'Adjacent (0.0, Float'Last));
return (Float'Adjacent (0.0, Float'First), Float'Adjacent (0.0, Float'Last));
end if;
end if;
end "+";</lang>
end "+";</syntaxhighlight>
The implementation uses the attribute T'Machine_Rounds to determine if rounding is performed on inexact results. If the machine rounds a symmetric interval around the result is used. When the machine does not round, it truncates. Truncating is rounding towards zero. In this case the implementation is twice better (in terms of the result interval width), because depending on its sign, the outcome of addition can be taken for either of the bounds. Unfortunately most of modern processors are rounding.
The implementation uses the attribute T'Machine_Rounds to determine if rounding is performed on inexact results. If the machine rounds a symmetric interval around the result is used. When the machine does not round, it truncates. Truncating is rounding towards zero. In this case the implementation is twice better (in terms of the result interval width), because depending on its sign, the outcome of addition can be taken for either of the bounds. Unfortunately most of modern processors are rounding.


Test program:
Test program:
<lang Ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
procedure Test_Interval_Addition is
procedure Test_Interval_Addition is
-- Definitions from above
-- Definitions from above
Line 64: Line 64:
begin
begin
Put (1.14 + 2000.0);
Put (1.14 + 2000.0);
end Test_Interval_Addition;</lang>
end Test_Interval_Addition;</syntaxhighlight>
Sample output:
Sample output:
<pre> 2.00113989257813E+03, 2.00114013671875E+03</pre>
<pre> 2.00113989257813E+03, 2.00114013671875E+03</pre>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
<lang ahk>Msgbox % IntervalAdd(1,2) ; [2.999999,3.000001]
<syntaxhighlight lang="ahk">Msgbox % IntervalAdd(1,2) ; [2.999999,3.000001]


SetFormat, FloatFast, 0.20
SetFormat, FloatFast, 0.20
Line 82: Line 82:
err:=0.1**(SubStr(A_FormatFloat,3) > 15 ? 15 : SubStr(A_FormatFloat,3))
err:=0.1**(SubStr(A_FormatFloat,3) > 15 ? 15 : SubStr(A_FormatFloat,3))
Return "[" a+b-err ","a+b+err "]"
Return "[" a+b-err ","a+b+err "]"
}</lang>
}</syntaxhighlight>


=={{header|C}}==
=={{header|C}}==
Line 97: Line 97:


=== C99 with fesetround() ===
=== C99 with fesetround() ===
<lang c>#include <fenv.h> /* fegetround(), fesetround() */
<syntaxhighlight lang="c">#include <fenv.h> /* fegetround(), fesetround() */
#include <stdio.h> /* printf() */
#include <stdio.h> /* printf() */
Line 146: Line 146:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 169: Line 169:
{{works with|MinGW}}
{{works with|MinGW}}


<lang c>#include <float.h> /* _controlfp() */
<syntaxhighlight lang="c">#include <float.h> /* _controlfp() */
#include <stdio.h> /* printf() */
#include <stdio.h> /* printf() */


Line 217: Line 217:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


=== fpsetround() ===
=== fpsetround() ===
{{works with|OpenBSD|4.8/amd64}}
{{works with|OpenBSD|4.8/amd64}}


<lang c>#include <ieeefp.h> /* fpsetround() */
<syntaxhighlight lang="c">#include <ieeefp.h> /* fpsetround() */
#include <stdio.h> /* printf() */
#include <stdio.h> /* printf() */


Line 270: Line 270:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


Output from OpenBSD: <pre>1 + 2 =
Output from OpenBSD: <pre>1 + 2 =
Line 291: Line 291:
=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
{{trans|Java}}
{{trans|Java}}
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


namespace SafeAddition {
namespace SafeAddition {
Line 330: Line 330:
}
}
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>(1.2 + 0.03) is in the range (1.23, 1.23)</pre>
<pre>(1.2 + 0.03) is in the range (1.23, 1.23)</pre>
Line 336: Line 336:
=={{header|C++}}==
=={{header|C++}}==
{{trans|C#}}
{{trans|C#}}
<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">#include <iostream>
#include <tuple>
#include <tuple>


Line 378: Line 378:


return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>(1.200000 + 0.030000) is in the range (1.2299998998641968, 1.2300001382827759)</pre>
<pre>(1.200000 + 0.030000) is in the range (1.2299998998641968, 1.2300001382827759)</pre>
Line 384: Line 384:
=={{header|D}}==
=={{header|D}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang D>import std.traits;
<syntaxhighlight lang="d">import std.traits;
auto safeAdd(T)(T a, T b)
auto safeAdd(T)(T a, T b)
if (isFloatingPoint!T) {
if (isFloatingPoint!T) {
Line 399: Line 399:
auto r = safeAdd(a, b);
auto r = safeAdd(a, b);
writefln("(%s + %s) is in the range %0.16f .. %0.16f", a, b, r.d, r.u);
writefln("(%s + %s) is in the range %0.16f .. %0.16f", a, b, r.d, r.u);
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 416: Line 416:
E currently inherits [[Java]]'s choices of [[IEEE]] floating point behavior, including round to nearest. Therefore, as in the Ada example, given ignorance of the actual direction of rounding, we must take one step away in ''both'' directions to get a correct interval.
E currently inherits [[Java]]'s choices of [[IEEE]] floating point behavior, including round to nearest. Therefore, as in the Ada example, given ignorance of the actual direction of rounding, we must take one step away in ''both'' directions to get a correct interval.


<lang e>def makeInterval(a :float64, b :float64) {
<syntaxhighlight lang="e">def makeInterval(a :float64, b :float64) {
require(a <= b)
require(a <= b)
def interval {
def interval {
Line 432: Line 432:
}
}
return interval
return interval
}</lang>
}</syntaxhighlight>


<lang e>? makeInterval(1.14, 1.14) + makeInterval(2000.0, 2000.0)
<syntaxhighlight lang="e">? makeInterval(1.14, 1.14) + makeInterval(2000.0, 2000.0)
# value: [2001.1399999999999, 2001.1400000000003]</lang>
# value: [2001.1399999999999, 2001.1400000000003]</syntaxhighlight>


E provides only 64-bit "double precision" floats, and always prints them with sufficient decimal places to reproduce the original floating point number exactly.
E provides only 64-bit "double precision" floats, and always prints them with sufficient decimal places to reproduce the original floating point number exactly.
Line 441: Line 441:
=={{header|Forth}}==
=={{header|Forth}}==
{{trans|Tcl}}
{{trans|Tcl}}
<lang forth>c-library m
<syntaxhighlight lang="forth">c-library m
s" m" add-lib
s" m" add-lib
\c #include <math.h>
\c #include <math.h>
Line 455: Line 455:


: savef+ ( F: r1 r2 -- r3 r4 ) \ r4 <= r1+r2 <= r3
: savef+ ( F: r1 r2 -- r3 r4 ) \ r4 <= r1+r2 <= r3
f+ fdup fstepup fswap fstepdown ;</lang>
f+ fdup fstepup fswap fstepdown ;</syntaxhighlight>
{{output}}
{{output}}
<pre>
<pre>
Line 465: Line 465:
=={{header|Go}}==
=={{header|Go}}==
{{trans|Tcl}}
{{trans|Tcl}}
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 494: Line 494:
a, b := 1.2, .03
a, b := 1.2, .03
fmt.Println(a, b, safeAdd(a, b))
fmt.Println(a, b, safeAdd(a, b))
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 502: Line 502:
=={{header|Hare}}==
=={{header|Hare}}==
{{trans|C}}
{{trans|C}}
<lang hare>use fmt;
<syntaxhighlight lang="hare">use fmt;
use math;
use math;


Line 528: Line 528:
math::setround(orig);
math::setround(orig);
return interval{a = r0, b = r1};
return interval{a = r0, b = r1};
};</lang>
};</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 539: Line 539:
=={{header|J}}==
=={{header|J}}==
J uses 64 bit IEEE floating points, providing 53 binary digits of accuracy.
J uses 64 bit IEEE floating points, providing 53 binary digits of accuracy.
<lang j> err =. 2^ 53-~ 2 <.@^. | NB. get the size of one-half unit in the last place
<syntaxhighlight lang="j"> err =. 2^ 53-~ 2 <.@^. | NB. get the size of one-half unit in the last place
safeadd =. + (-,+) +&err
safeadd =. + (-,+) +&err
0j15": 1.14 safeadd 2000.0 NB. print with 15 digits after the decimal
0j15": 1.14 safeadd 2000.0 NB. print with 15 digits after the decimal
2001.139999999999873 2001.140000000000327</lang>
2001.139999999999873 2001.140000000000327</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang Java>public class SafeAddition {
<syntaxhighlight lang="java">public class SafeAddition {
private static double stepDown(double d) {
private static double stepDown(double d) {
return Math.nextAfter(d, Double.NEGATIVE_INFINITY);
return Math.nextAfter(d, Double.NEGATIVE_INFINITY);
Line 565: Line 565:
System.out.printf("(%.2f + %.2f) is in the range %.16f..%.16f", a, b, result[0], result[1]);
System.out.printf("(%.2f + %.2f) is in the range %.16f..%.16f", a, b, result[0], result[1]);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>(1.20 + 0.03) is in the range 1.2299999999999998..1.2300000000000002</pre>
<pre>(1.20 + 0.03) is in the range 1.2299999999999998..1.2300000000000002</pre>
Line 571: Line 571:
=={{header|Julia}}==
=={{header|Julia}}==
Julia has the IntervalArithmetic module, which provides arithmetic with defined precision along with the option of simply computing with actual two-number intervals:
Julia has the IntervalArithmetic module, which provides arithmetic with defined precision along with the option of simply computing with actual two-number intervals:
<syntaxhighlight lang="julia">
<lang Julia>
julia> using IntervalArithmetic
julia> using IntervalArithmetic


Line 591: Line 591:
julia> a + b
julia> a + b
[0.399999, 0.900001]
[0.399999, 0.900001]
</syntaxhighlight>
</lang>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Tcl}}
{{trans|Tcl}}
<lang scala>// version 1.1.2
<syntaxhighlight lang="scala">// version 1.1.2


fun stepDown(d: Double) = Math.nextAfter(d, Double.NEGATIVE_INFINITY)
fun stepDown(d: Double) = Math.nextAfter(d, Double.NEGATIVE_INFINITY)
Line 607: Line 607:
val b = 0.03
val b = 0.03
println("($a + $b) is in the range ${safeAdd(a, b)}")
println("($a + $b) is in the range ${safeAdd(a, b)}")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 619: Line 619:
=={{header|Nim}}==
=={{header|Nim}}==
{{trans|C}}
{{trans|C}}
<lang nim>import fenv, strutils
<syntaxhighlight lang="nim">import fenv, strutils


proc `++`(a, b: float): tuple[lower, upper: float] =
proc `++`(a, b: float): tuple[lower, upper: float] =
Line 638: Line 638:
echo x.ff, " + ", y.ff, " ="
echo x.ff, " + ", y.ff, " ="
echo " [", d.ff, ", ", u.ff, "]"
echo " [", d.ff, ", ", u.ff, "]"
echo " size ", (u - d).ff, "\n"</lang>
echo " size ", (u - d).ff, "\n"</syntaxhighlight>
Output:
Output:
<pre>1.0000000000000000 + 2.0000000000000000 =
<pre>1.0000000000000000 + 2.0000000000000000 =
Line 658: Line 658:
=={{header|Perl}}==
=={{header|Perl}}==
There are ways avoid this whole problem (e.g. <code>Math::Decimal</code>), but another module suffices for this task.
There are ways avoid this whole problem (e.g. <code>Math::Decimal</code>), but another module suffices for this task.
<lang perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
use Data::IEEE754::Tools <nextUp nextDown>;
use Data::IEEE754::Tools <nextUp nextDown>;
Line 668: Line 668:
}
}


printf "%.17f (%.17f, %.17f)\n", safe_add (1/9,1/7);</lang>
printf "%.17f (%.17f, %.17f)\n", safe_add (1/9,1/7);</syntaxhighlight>
{{out}}
{{out}}
<pre>0.25396825396825395 (0.25396825396825390, 0.25396825396825401)</pre>
<pre>0.25396825396825395 (0.25396825396825390, 0.25396825396825401)</pre>
Line 680: Line 680:
Not surprisingly you have to get a bit down and dirty to manage this sort of stuff in Phix.
Not surprisingly you have to get a bit down and dirty to manage this sort of stuff in Phix.


<!--<lang Phix>-->
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">VM</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pFPU</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- :%down53 etc</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">VM</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pFPU</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- :%down53 etc</span>
Line 734: Line 734:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" size %.16g\n\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">low</span><span style="color: #0000FF;">);</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" size %.16g\n\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">low</span><span style="color: #0000FF;">);</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 763: Line 763:
Python doesn't include a module that returns an interval for safe addition, however, it does [http://docs.python.org/library/math.html#math.fsum include] a routine for performing additions of floating point numbers whilst preserving precision:
Python doesn't include a module that returns an interval for safe addition, however, it does [http://docs.python.org/library/math.html#math.fsum include] a routine for performing additions of floating point numbers whilst preserving precision:


<lang python>>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
<syntaxhighlight lang="python">>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
0.9999999999999999
0.9999999999999999
>>> from math import fsum
>>> from math import fsum
>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
1.0</lang>
1.0</syntaxhighlight>


=={{header|Racket}}==
=={{header|Racket}}==


<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
#lang racket


Line 799: Line 799:
;; literals
;; literals
(bf+ (bf "1.14") (bf "2000.0"))
(bf+ (bf "1.14") (bf "2000.0"))
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
Line 831: Line 831:




<lang perl6>say "Floating points: (Nums)";
<syntaxhighlight lang="raku" line>say "Floating points: (Nums)";
say "Error: " ~ (2**-53).Num;
say "Error: " ~ (2**-53).Num;


Line 858: Line 858:
say "\nRaku default stringification for 1.5**63:\n" ~ $rat; # standard stringification
say "\nRaku default stringification for 1.5**63:\n" ~ $rat; # standard stringification
say "\nRat::Precise stringification for 1.5**63:\n" ~$rat.precise; # full precision
say "\nRat::Precise stringification for 1.5**63:\n" ~$rat.precise; # full precision
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>Floating points: (Nums)
<pre>Floating points: (Nums)
Line 887: Line 887:
constrained by how much virtual memory is (or can be) allocated.
constrained by how much virtual memory is (or can be) allocated.
<br>Eight million digits seems about a practical high end, however.
<br>Eight million digits seems about a practical high end, however.
<lang rexx>numeric digits 1000 /*defines precision to be 1,000 decimal digits. */
<syntaxhighlight lang="rexx">numeric digits 1000 /*defines precision to be 1,000 decimal digits. */


y=digits() /*sets Y to existing number of decimal digits.*/
y=digits() /*sets Y to existing number of decimal digits.*/


numeric digits y + y%10 /*increase the (numeric) decimal digits by 10%.*/</lang><br><br>
numeric digits y + y%10 /*increase the (numeric) decimal digits by 10%.*/</syntaxhighlight><br><br>


=={{header|Ruby}}==
=={{header|Ruby}}==
Line 898: Line 898:
When adding <tt>BigDecimal</tt> values, <tt>a + b</tt> is always safe. This example uses <tt>a.add(b, prec)</tt>, which is not safe because it rounds to <tt>prec</tt> digits. This example computes a safe interval by rounding to both floor and ceiling.
When adding <tt>BigDecimal</tt> values, <tt>a + b</tt> is always safe. This example uses <tt>a.add(b, prec)</tt>, which is not safe because it rounds to <tt>prec</tt> digits. This example computes a safe interval by rounding to both floor and ceiling.


<lang ruby>require 'bigdecimal'
<syntaxhighlight lang="ruby">require 'bigdecimal'
require 'bigdecimal/util' # String#to_d
require 'bigdecimal/util' # String#to_d


Line 920: Line 920:
["0.1", "0.00002"],
["0.1", "0.00002"],
["0.1", "-0.00002"],
["0.1", "-0.00002"],
].each { |a, b| puts "#{a} + #{b} = #{safe_add(a, b, 3)}" }</lang>
].each { |a, b| puts "#{a} + #{b} = #{safe_add(a, b, 3)}" }</syntaxhighlight>


Output: <pre>1 + 2 = 0.3E1..0.3E1
Output: <pre>1 + 2 = 0.3E1..0.3E1
Line 928: Line 928:


=={{header|Scala}}==
=={{header|Scala}}==
<lang Scala>object SafeAddition extends App {
<syntaxhighlight lang="scala">object SafeAddition extends App {
val (a, b) = (1.2, 0.03)
val (a, b) = (1.2, 0.03)
val result = safeAdd(a, b)
val result = safeAdd(a, b)
Line 940: Line 940:
println(f"($a%.2f + $b%.2f) is in the range ${result.head}%.16f .. ${result.last}%.16f")
println(f"($a%.2f + $b%.2f) is in the range ${result.head}%.16f .. ${result.last}%.16f")


}</lang>
}</syntaxhighlight>


=={{header|Swift}}==
=={{header|Swift}}==
<lang swift>let a = 1.2
<syntaxhighlight lang="swift">let a = 1.2
let b = 0.03
let b = 0.03


print("\(a) + \(b) is in the range \((a + b).nextDown)...\((a + b).nextUp)")</lang>
print("\(a) + \(b) is in the range \((a + b).nextDown)...\((a + b).nextUp)")</syntaxhighlight>


{{out}}
{{out}}
Line 955: Line 955:
<br>
<br>
{{libheader|critcl}}
{{libheader|critcl}}
<lang tcl>package require critcl
<syntaxhighlight lang="tcl">package require critcl
package provide stepaway 1.0
package provide stepaway 1.0
critcl::ccode {
critcl::ccode {
Line 966: Line 966:
critcl::cproc stepdown {double value} double {
critcl::cproc stepdown {double value} double {
return nextafter(value, -DBL_MAX);
return nextafter(value, -DBL_MAX);
}</lang>
}</syntaxhighlight>
With that package it's then trivial to define a "safe addition" that returns an interval as a list (lower bound, upper bound).
With that package it's then trivial to define a "safe addition" that returns an interval as a list (lower bound, upper bound).
<lang tcl>package require stepaway
<syntaxhighlight lang="tcl">package require stepaway
proc safe+ {a b} {
proc safe+ {a b} {
set val [expr {double($a) + $b}]
set val [expr {double($a) + $b}]
return [list [stepdown $val] [stepup $val]]
return [list [stepdown $val] [stepup $val]]
}</lang>
}</syntaxhighlight>




=={{header|Transd}}==
=={{header|Transd}}==
<lang scheme>#lang transd
<syntaxhighlight lang="scheme">#lang transd


MainModule : {
MainModule : {
Line 988: Line 988:
(lout "(+ " a " " b ") is in the range: " prec: 20 (safeAdd a b))
(lout "(+ " a " " b ") is in the range: " prec: 20 (safeAdd a b))
)
)
}</lang>{{out}}
}</syntaxhighlight>{{out}}
<pre>
<pre>
(+ 1.2 0.03) is in the range: [1.2299999999999997602, 1.2300000000000002043]
(+ 1.2 0.03) is in the range: [1.2299999999999997602, 1.2300000000000002043]
Line 997: Line 997:


However, if Wren is embedded in a suitable C program, then we can ask the latter to call it for us and pass back the result.
However, if Wren is embedded in a suitable C program, then we can ask the latter to call it for us and pass back the result.
<lang ecmascript>/* safe_addition.wren */
<syntaxhighlight lang="ecmascript">/* safe_addition.wren */
class Interval {
class Interval {
construct new(lower, upper) {
construct new(lower, upper) {
Line 1,021: Line 1,021:
var a = 1.2
var a = 1.2
var b = 0.03
var b = 0.03
System.print("(%(a) + %(b)) is in the range %(Interval.safeAdd(a,b))")</lang>
System.print("(%(a) + %(b)) is in the range %(Interval.safeAdd(a,b))")</syntaxhighlight>


which we embed in the following C program and run it (using GCC 9.3.0).
which we embed in the following C program and run it (using GCC 9.3.0).


Note that Wren's built-in print statement never displays numbers with more than 14 digit accuracy. However, if the interval bounds had been displayed directly from C with 17 digit accuracy (the maximum for the 'double' type), there would have been a marginal difference between them, namely: [1.2299999999999998, 1.2300000000000002].
Note that Wren's built-in print statement never displays numbers with more than 14 digit accuracy. However, if the interval bounds had been displayed directly from C with 17 digit accuracy (the maximum for the 'double' type), there would have been a marginal difference between them, namely: [1.2299999999999998, 1.2300000000000002].
<lang C>#include <stdlib.h>
<syntaxhighlight lang="c">#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <math.h>
#include <math.h>
Line 1,108: Line 1,108:
free(script);
free(script);
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}