Safe addition: Difference between revisions
Content added Content deleted
(→{{header|C}}: Add solution with Microsoft _controlfp().) |
(→{{header|REXX}}: Add Ruby using bigdecimal.) |
||
Line 251: | Line 251: | ||
numeric digits digits()+digits()%10 /*increase digits by 10%.*/ |
numeric digits digits()+digits()%10 /*increase digits by 10%.*/ |
||
</lang> |
</lang> |
||
=={{header|Ruby}}== |
|||
The <tt>Float</tt> class provides no way to change the rounding mode. We instead use the <tt>BigDecimal</tt> class from the standard library. <tt>BigDecimal</tt> is a floating-point number of radix 10 with arbitrary precision. |
|||
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. |
|||
{{libheader|bigdecimal}} |
|||
<lang ruby>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)}" }</lang> |
|||
Output: <pre>1 + 2 = 0.3E1..0.3E1 |
|||
0.1 + 0.2 = 0.3E0..0.3E0 |
|||
0.1 + 0.00002 = 0.1E0..0.101E0 |
|||
0.1 + -0.00002 = 0.999E-1..0.1E0</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |