tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
8
Task/Safe-addition/0DESCRIPTION
Normal file
8
Task/Safe-addition/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Implementation of [[wp:Interval_arithmetic|interval arithmetic]] and more generally fuzzy number arithmetic require operations that yield safe upper and lower bounds of the exact result. For example, for an addition, it is the operations *↑ and *↓ defined as: ''a'' +↓ ''b'' ≤ ''a'' + ''b'' ≤ ''a'' +↑ ''b''. Additionally it is desired that the width of the interval (''a'' +↑ ''b'') - (''a'' +↓ ''b'') would be about the machine epsilon after removing the exponent part.
|
||||
|
||||
Differently to the standard floating-point arithmetic, safe interval arithmetic is '''accurate''' (but still imprecise). I.e. the result of each defined operation contains (though does not identify) the exact mathematical outcome.
|
||||
|
||||
Usually a [[wp:Floating_Point_Unit|FPU's]] have machine +,-,*,/ operations accurate within the machine precision. To illustrate it, let us consider a machine with decimal floating-point arithmetic that has the precision is 3 decimal points. If the result of the machine addition is 1.23, then the exact mathematical result is within the interval ]1.22, 1.24[. When the machine rounds towards zero, then the exact result is within [1.23,1.24[. This is the basis for an implementation of safe addition.
|
||||
|
||||
===Task===
|
||||
Show how +↓ and +↑ can be implemented in your language using the standard floating-point type. Define an interval type based on the standard floating-point one, and implement an interval-valued addition of two floating-point numbers considering them exact, in short an operation that yields the interval [''a'' +↓ ''b'', ''a'' +↑ ''b''].
|
||||
2
Task/Safe-addition/1META.yaml
Normal file
2
Task/Safe-addition/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Arithmetic operations
|
||||
4
Task/Safe-addition/Ada/safe-addition-1.ada
Normal file
4
Task/Safe-addition/Ada/safe-addition-1.ada
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
type Interval is record
|
||||
Lower : Float;
|
||||
Upper : Float;
|
||||
end record;
|
||||
19
Task/Safe-addition/Ada/safe-addition-2.ada
Normal file
19
Task/Safe-addition/Ada/safe-addition-2.ada
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
function "+" (A, B : Float) return Interval is
|
||||
Result : constant Float := A + B;
|
||||
begin
|
||||
if Result < 0.0 then
|
||||
if Float'Machine_Rounds then
|
||||
return (Float'Adjacent (Result, Float'First), Float'Adjacent (Result, 0.0));
|
||||
else
|
||||
return (Float'Adjacent (Result, Float'First), Result);
|
||||
end if;
|
||||
elsif Result > 0.0 then
|
||||
if Float'Machine_Rounds then
|
||||
return (Float'Adjacent (Result, 0.0), Float'Adjacent (Result, Float'Last));
|
||||
else
|
||||
return (Result, Float'Adjacent (Result, Float'Last));
|
||||
end if;
|
||||
else -- Underflow
|
||||
return (Float'Adjacent (0.0, Float'First), Float'Adjacent (0.0, Float'Last));
|
||||
end if;
|
||||
end "+";
|
||||
10
Task/Safe-addition/Ada/safe-addition-3.ada
Normal file
10
Task/Safe-addition/Ada/safe-addition-3.ada
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
procedure Test_Interval_Addition is
|
||||
-- Definitions from above
|
||||
procedure Put (I : Interval) is
|
||||
begin
|
||||
Put (Long_Float'Image (Long_Float (I.Lower)) & "," & Long_Float'Image (Long_Float (I.Upper)));
|
||||
end Put;
|
||||
begin
|
||||
Put (1.14 + 2000.0);
|
||||
end Test_Interval_Addition;
|
||||
50
Task/Safe-addition/C/safe-addition-1.c
Normal file
50
Task/Safe-addition/C/safe-addition-1.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <fenv.h> /* fegetround(), fesetround() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
unsigned int orig;
|
||||
|
||||
orig = fegetround();
|
||||
fesetround(FE_DOWNWARD); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
fesetround(FE_UPWARD); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
fesetround(orig);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. %.17g gives the best output.
|
||||
* %.16g or plain %g gives not enough digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
49
Task/Safe-addition/C/safe-addition-2.c
Normal file
49
Task/Safe-addition/C/safe-addition-2.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <float.h> /* _controlfp() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
unsigned int orig;
|
||||
|
||||
orig = _controlfp(0, 0);
|
||||
_controlfp(_RC_DOWN, _MCW_RC); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
_controlfp(_RC_UP, _MCW_RC); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
_controlfp(orig, _MCW_RC);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. %.17g gives the best output.
|
||||
* %.16g or plain %g gives not enough digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
49
Task/Safe-addition/C/safe-addition-3.c
Normal file
49
Task/Safe-addition/C/safe-addition-3.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <ieeefp.h> /* fpsetround() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
fp_rnd orig;
|
||||
|
||||
orig = fpsetround(FP_RM); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
fpsetround(FP_RP); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
fpsetround(orig);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. With OpenBSD libc, %.17g gives
|
||||
* the best output; %.16g or plain %g gives not enough
|
||||
* digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
17
Task/Safe-addition/E/safe-addition-1.e
Normal file
17
Task/Safe-addition/E/safe-addition-1.e
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
def makeInterval(a :float64, b :float64) {
|
||||
require(a <= b)
|
||||
def interval {
|
||||
to least() { return a }
|
||||
to greatest() { return b }
|
||||
to __printOn(out) {
|
||||
out.print("[", a, ", ", b, "]")
|
||||
}
|
||||
to add(other) {
|
||||
require(a <=> b)
|
||||
require(other.least() <=> other.greatest())
|
||||
def result := a + other.least()
|
||||
return makeInterval(result.previous(), result.next())
|
||||
}
|
||||
}
|
||||
return interval
|
||||
}
|
||||
2
Task/Safe-addition/E/safe-addition-2.e
Normal file
2
Task/Safe-addition/E/safe-addition-2.e
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
? makeInterval(1.14, 1.14) + makeInterval(2000.0, 2000.0)
|
||||
# value: [2001.1399999999999, 2001.1400000000003]
|
||||
30
Task/Safe-addition/Go/safe-addition.go
Normal file
30
Task/Safe-addition/Go/safe-addition.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// type requested by task
|
||||
type interval struct {
|
||||
lower, upper float64
|
||||
}
|
||||
|
||||
// a constructor
|
||||
func stepAway(x float64) interval {
|
||||
return interval {
|
||||
math.Nextafter(x, math.Inf(-1)),
|
||||
math.Nextafter(x, math.Inf(1))}
|
||||
}
|
||||
|
||||
// function requested by task
|
||||
func safeAdd(a, b float64) interval {
|
||||
return stepAway(a + b)
|
||||
|
||||
}
|
||||
|
||||
// example
|
||||
func main() {
|
||||
a, b := 1.2, .03
|
||||
fmt.Println(a, b, safeAdd(a, b))
|
||||
}
|
||||
4
Task/Safe-addition/J/safe-addition.j
Normal file
4
Task/Safe-addition/J/safe-addition.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
err =. 2^ 53-~ 2 <.@^. | NB. get the size of one-half unit in the last place
|
||||
safeadd =. + (-,+) +&err
|
||||
0j15": 1.14 safeadd 2000.0 NB. print with 15 digits after the decimal
|
||||
2001.139999999999873 2001.140000000000327
|
||||
5
Task/Safe-addition/Python/safe-addition.py
Normal file
5
Task/Safe-addition/Python/safe-addition.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
|
||||
0.9999999999999999
|
||||
>>> from math import fsum
|
||||
>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
|
||||
1.0
|
||||
5
Task/Safe-addition/REXX/safe-addition.rexx
Normal file
5
Task/Safe-addition/REXX/safe-addition.rexx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
numeric digits 1000 /*defines precision to be 1000 digits. */
|
||||
|
||||
y=digits() /*sets Y to existing number of digits.*/
|
||||
|
||||
numeric digits digits()+digits()%10 /*increase digits by 10%.*/
|
||||
23
Task/Safe-addition/Ruby/safe-addition.rb
Normal file
23
Task/Safe-addition/Ruby/safe-addition.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
require 'bigdecimal'
|
||||
require 'bigdecimal/util' # String#to_d
|
||||
|
||||
def safe_add(a, b, prec)
|
||||
a, b = a.to_d, b.to_d
|
||||
rm = BigDecimal::ROUND_MODE
|
||||
orig = BigDecimal.mode(rm)
|
||||
|
||||
BigDecimal.mode(rm, BigDecimal::ROUND_FLOOR)
|
||||
low = a.add(b, prec)
|
||||
|
||||
BigDecimal.mode(rm, BigDecimal::ROUND_CEILING)
|
||||
high = a.add(b, prec)
|
||||
|
||||
BigDecimal.mode(rm, orig)
|
||||
low..high
|
||||
end
|
||||
|
||||
[["1", "2"],
|
||||
["0.1", "0.2"],
|
||||
["0.1", "0.00002"],
|
||||
["0.1", "-0.00002"],
|
||||
].each { |a, b| puts "#{a} + #{b} = #{safe_add(a, b, 3)}" }
|
||||
12
Task/Safe-addition/Tcl/safe-addition-1.tcl
Normal file
12
Task/Safe-addition/Tcl/safe-addition-1.tcl
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package require critcl
|
||||
package provide stepaway 1.0
|
||||
critcl::ccode {
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
}
|
||||
critcl::cproc stepup {double value} double {
|
||||
return nextafter(value, DBL_MAX);
|
||||
}
|
||||
critcl::cproc stepdown {double value} double {
|
||||
return nextafter(value, -DBL_MAX);
|
||||
}
|
||||
5
Task/Safe-addition/Tcl/safe-addition-2.tcl
Normal file
5
Task/Safe-addition/Tcl/safe-addition-2.tcl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package require stepaway
|
||||
proc safe+ {a b} {
|
||||
set val [expr {double($a) + $b}]
|
||||
return [list [stepdown $val] [stepup $val]]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue