I am working on a Scheme program, where I need at some place a pair of a floatingpoint counter and the same counter as formated string. I am having issues with the number to string conversion.
Can someone explain me these inaccuracies in this code ?
(letrec ((ground-loop (lambda (times count step)
(if (= times 250)
(begin
(display "exit")
(newline)
)
(begin
(display (* times step)) (newline)
(display (number->string (* times step)))(newline)
(newline)
(newline)
(ground-loop (+ times 1) (* times step) step)
)
)
)
))
(ground-loop 0 0 0.05)
)
Part of the output looks like that
7.25
7.25
7.3
7.300000000000001
7.35
7.350000000000001
7.4
7.4
7.45
7.45
7.5
7.5
7.55
7.550000000000001
7.6
7.600000000000001
7.65
7.65
I am aware of floating point inaccuracies and tried several forms of increasing the counter but the issue is in the conversion itself.
Any ideas for an easy fix? Tried a bit with explicitly rounded numbers but this did not do the job. The results even vary from IDE and environment to environment. Do I really have to do string manipulation after conversion?
The very weird thing in my case is having an exact numeric result but the string is off.
Thank you
It looks to me as if:
the native float type (the type you get by reading 1.0) of your implementation is IEEE double float;
the display of your Scheme is not printing such floats 'correctly' (see below, I'm no sure this means it's buggy);
your number->string is doing the right thing.
By 'correctly' above I mean 'in a way so that reading what display printed returns an equivalent number'. I am not at all sure that display is required to be correct in this restrictive sense however, so I am not sure whether it's a bug. Someone who understands the Scheme standards better than I do might be able to comment on that.
In particular if the native float type of the languageis an IEEE double float, then, for instance:
(= (* 0.05 3) 0.15)
is false, as is
(= (* 0.05 146) 7.3)
Which is the example you have in the first line of your output.
So you certainly should not assume that your program will ever produce a number equal to the number you get by reading 7.3 for instance, because it won't.
In the above I have carefully avoided printing the numbers out, and that's because I'm not sure display is reliable on this, and in particular I'm not sure your display is reliable or that it is required to be.
Well, I have a Lisp implementation to hand which is reliable about this. In this system the default float format is a single-precision IEEE float, and I can get the reader to read double floats with, for instance 1.0d0. So, in this implementation you can see the results:
> (* 0.05d0 3)
0.15000000000000002D0
> (* 0.05d0 146)
7.300000000000001D0
And you'll see that these are exactly (up to the double-precision indicator) what number->string is giving you and not what display is giving you.
If what you want to do is to get a representation of the number in such a way that reading it will return an equivalent number, then number->string is what you should trust. In particular R5RS says in section 6.2.6 that:
(let ((number number)
(radix radix))
(eqv? number
(string->number (number->string number
radix)
radix)))
is true, and 'it is an error if no possible result makes this expression true'.
You can check the behaviour of number->float & float->number over a range of numbers by, for instance (this may assume a more recent or featurefull Scheme than you have):
(define (verify-float-conversion base times)
(define (good? f)
(eqv? (string->number (number->string f)) f))
(let loop ([i 0]
[bads '()])
(let ([c (* base i)])
(if (>= i times)
(values (null? bads) (reverse bads))
(loop (+ i 1) (if (good? c) bads (cons c bads)))))))
Then you should get
> (verify-float-conversion 0.05 10000)
#t
()
More generally using floats, still more floats that are the result of some computation more complicated than reading them some input source, as unique indices into any kind of tabular structure is fraught with danger to put it rather mildly: floating-point errors mean that it's just really dangerous to assume that (= a b) is true for floats even when it mathematically should be.
If you want such indices do exact arithmetic instead, and convert the results of that arithmetic to floats at the point you need to do computations. I believe (but am not sure) that Scheme implementations are nowadays required to support exact rational arithmetic (certainly this seems to be true for R6RS), so if you want to count 20ths (say) you can do so by counting in units of 1/20, which is exact, and then constructing floats when you need them.
It's probably safe to compare floats in the case that if you are for instance comparing a float you got by taking some initial float value and multiplying it by a machine integer and comparing it with some earlier version of itself which you have read by string->number. But if the calculation your doing is more complicated than that you need to be quite careful.
In C#, the result of Math.Round(2.5) is 2.
It is supposed to be 3, isn't it? Why is it 2 instead in C#?
Firstly, this wouldn't be a C# bug anyway - it would be a .NET bug. C# is the language - it doesn't decide how Math.Round is implemented.
And secondly, no - if you read the docs, you'll see that the default rounding is "round to even" (banker's rounding):
Return ValueType: System.DoubleThe integer nearest a. If the
fractional component of a is halfway
between two integers, one of which is
even and the other odd, then the even
number is returned. Note that this
method returns a Double instead of an
integral type.
RemarksThe behavior of this method follows IEEE Standard 754,
section 4. This kind of rounding is
sometimes called rounding to nearest,
or banker's rounding. It minimizes
rounding errors that result from
consistently rounding a midpoint value
in a single direction.
You can specify how Math.Round should round mid-points using an overload which takes a MidpointRounding value. There's one overload with a MidpointRounding corresponding to each of the overloads which doesn't have one:
Round(Decimal) / Round(Decimal, MidpointRounding)
Round(Double) / Round(Double, MidpointRounding)
Round(Decimal, Int32) / Round(Decimal, Int32, MidpointRounding)
Round(Double, Int32) / Round(Double, Int32, MidpointRounding)
Whether this default was well chosen or not is a different matter. (MidpointRounding was only introduced in .NET 2.0. Before then I'm not sure there was any easy way of implementing the desired behaviour without doing it yourself.) In particular, history has shown that it's not the expected behaviour - and in most cases that's a cardinal sin in API design. I can see why Banker's Rounding is useful... but it's still a surprise to many.
You may be interested to take a look at the nearest Java equivalent enum (RoundingMode) which offers even more options. (It doesn't just deal with midpoints.)
That's called rounding to even (or banker's rounding), which is a valid rounding strategy for minimizing accrued errors in sums (MidpointRounding.ToEven). The theory is that, if you always round a 0.5 number in the same direction, the errors will accrue faster (round-to-even is supposed to minimize that) (a).
Follow these links for the MSDN descriptions of:
Math.Floor, which rounds down towards negative infinity.
Math.Ceiling, which rounds up towards positive infinity.
Math.Truncate, which rounds up or down towards zero.
Math.Round, which rounds to the nearest integer or specified number of decimal places. You can specify the behavior if it's exactly equidistant between two possibilities, such as rounding so that the final digit is even ("Round(2.5,MidpointRounding.ToEven)" becoming 2) or so that it's further away from zero ("Round(2.5,MidpointRounding.AwayFromZero)" becoming 3).
The following diagram and table may help:
-3 -2 -1 0 1 2 3
+--|------+---------+----|----+--|------+----|----+-------|-+
a b c d e
a=-2.7 b=-0.5 c=0.3 d=1.5 e=2.8
====== ====== ===== ===== =====
Floor -3 -1 0 1 2
Ceiling -2 0 1 2 3
Truncate -2 0 0 1 2
Round(ToEven) -3 0 0 2 3
Round(AwayFromZero) -3 -1 0 2 3
Note that Round is a lot more powerful than it seems, simply because it can round to a specific number of decimal places. All the others round to zero decimals always. For example:
n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven); // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
With the other functions, you have to use multiply/divide trickery to achieve the same effect:
c = System.Math.Truncate (n * 100) / 100; // 3.14
d = System.Math.Ceiling (n * 100) / 100; // 3.15
(a) Of course, that theory depends on the fact that your data has an fairly even spread of values across the even halves (0.5, 2.5, 4.5, ...) and odd halves (1.5, 3.5, ...).
If all the "half-values" are evens (for example), the errors will accumulate just as fast as if you always rounded up.
You should check MSDN for Math.Round:
The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding.
You can specify the behavior of Math.Round using an overload:
Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3
Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2
From MSDN, Math.Round(double a) returns:
The integer nearest a. If the
fractional component of a is halfway
between two integers, one of which is
even and the other odd, then the even
number is returned.
... and so 2.5, being halfway between 2 and 3, is rounded down to the even number (2). this is called Banker's Rounding (or round-to-even), and is a commonly-used rounding standard.
Same MSDN article:
The behavior of this method follows
IEEE Standard 754, section 4. This
kind of rounding is sometimes called
rounding to nearest, or banker's
rounding. It minimizes rounding errors
that result from consistently rounding
a midpoint value in a single
direction.
You can specify a different rounding behavior by calling the overloads of Math.Round that take a MidpointRounding mode.
The nature of rounding
Consider the task of rounding a number that contains a fraction to, say, a whole number. The process of rounding in this circumstance is to determine which whole number best represents the number you are rounding.
In common, or 'arithmetic' rounding, it is clear that 2.1, 2.2, 2.3 and 2.4 round to 2.0; and 2.6, 2.7, 2.8 and 2.9 to 3.0.
That leaves 2.5, which is no nearer to 2.0 than it is to 3.0. It is up to you to choose between 2.0 and 3.0, either would be equally valid.
For minus numbers, -2.1, -2.2, -2.3 and -2.4, would become -2.0; and -2.6, 2.7, 2.8 and 2.9 would become -3.0 under arithmetic rounding.
For -2.5 a choice is needed between -2.0 and -3.0.
Other forms of rounding
'Rounding up' takes any number with decimal places and makes it the next 'whole' number. Thus not only do 2.5 and 2.6 round to 3.0, but so do 2.1 and 2.2.
Rounding up moves both positive and negative numbers away from zero. Eg. 2.5 to 3.0 and -2.5 to -3.0.
'Rounding down' truncates numbers by chopping off unwanted digits. This has the effect of moving numbers towards zero. Eg. 2.5 to 2.0 and -2.5 to -2.0
In "banker's rounding" - in its most common form - the .5 to be rounded is rounded either up or down so that the result of the rounding is always an even number. Thus 2.5 rounds to 2.0, 3.5 to 4.0, 4.5 to 4.0, 5.5 to 6.0, and so on.
'Alternate rounding' alternates the process for any .5 between rounding down and rounding up.
'Random rounding' rounds a .5 up or down on an entirely random basis.
Symmetry and asymmetry
A rounding function is said to be 'symmetric' if it either rounds all numbers away from zero or rounds all numbers towards zero.
A function is 'asymmetric' if rounds positive numbers towards zero and negative numbers away from zero.. Eg. 2.5 to 2.0; and -2.5 to -3.0.
Also asymmetric is a function that rounds positive numbers away from zero and negative numbers towards zero. Eg. 2.5 to 3.0; and -2.5 to -2.0.
Most of time people think of symmetric rounding, where -2.5 will be rounded towards -3.0 and 3.5 will be rounded towards 4.0. (in C# Round(AwayFromZero))
The default MidpointRounding.ToEven, or Bankers' rounding (2.5 become 2, 4.5 becomes 4 and so on) has stung me before with writing reports for accounting, so I'll write a few words of what I found out, previously and from looking into it for this post.
Who are these bankers that are rounding down on even numbers (British bankers perhaps!)?
From wikipedia
The origin of the term bankers'
rounding remains more obscure. If this
rounding method was ever a standard in
banking, the evidence has proved
extremely difficult to find. To the
contrary, section 2 of the European
Commission report The Introduction of
the Euro and the Rounding of Currency
Amounts suggests that there had
previously been no standard approach
to rounding in banking; and it
specifies that "half-way" amounts
should be rounded up.
It seems a very strange way of rounding particularly for banking, unless of course banks use to receive lots of deposits of even amounts. Deposit £2.4m, but we'll call it £2m sir.
The IEEE Standard 754 dates back to 1985 and gives both ways of rounding, but with banker's as the recommended by the standard. This wikipedia article has a long list of how languages implement rounding (correct me if any of the below are wrong) and most don't use Bankers' but the rounding you're taught at school:
C/C++ round() from math.h rounds away from zero (not banker's rounding)
Java Math.Round rounds away from zero (it floors the result, adds 0.5, casts to an integer). There's an alternative in BigDecimal
Perl uses a similar way to C
Javascript is the same as Java's Math.Round.
From MSDN:
By default, Math.Round uses
MidpointRounding.ToEven. Most people
are not familiar with "rounding to
even" as the alternative, "rounding
away from zero" is more commonly
taught in school. .NET defaults to
"Rounding to even" as it is
statistically superior because it
doesn't share the tendency of
"rounding away from zero" to round up
slightly more often than it rounds
down (assuming the numbers being
rounded tend to be positive.)
http://msdn.microsoft.com/en-us/library/system.math.round.aspx
Since Silverlight doesn't support the MidpointRounding option you have to write your own. Something like:
public double RoundCorrect(double d, int decimals)
{
double multiplier = Math.Pow(10, decimals);
if (d < 0)
multiplier *= -1;
return Math.Floor((d * multiplier) + 0.5) / multiplier;
}
For the examples including how to use this as an extension see the post: .NET and Silverlight Rounding
I had this problem where my SQL server rounds up 0.5 to 1 while my C# application didn't. So you would see two different results.
Here's an implementation with int/long. This is how Java rounds.
int roundedNumber = (int)Math.Floor(d + 0.5);
It's probably the most efficient method you could think of as well.
If you want to keep it a double and use decimal precision , then it's really just a matter of using exponents of 10 based on how many decimal places.
public double getRounding(double number, int decimalPoints)
{
double decimalPowerOfTen = Math.Pow(10, decimalPoints);
return Math.Floor(number * decimalPowerOfTen + 0.5)/ decimalPowerOfTen;
}
You can input a negative decimal for decimal points and it's word fine as well.
getRounding(239, -2) = 200
Silverlight doesn't support the MidpointRounding option.
Here's an extension method for Silverlight that adds the MidpointRounding enum:
public enum MidpointRounding
{
ToEven,
AwayFromZero
}
public static class DecimalExtensions
{
public static decimal Round(this decimal d, MidpointRounding mode)
{
return d.Round(0, mode);
}
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name="d">A Decimal number to be rounded.</param>
/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
{
if ( mode == MidpointRounding.ToEven )
{
return decimal.Round(d, decimals);
}
else
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
}
Source: http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/
Simple way is:
Math.Ceiling(decimal.Parse(yourNumber + ""));
Rounding numbers with .NET has the answer you are looking for.
Basically this is what it says:
Return Value
The number nearest value with precision equal to digits. If value is halfway between two numbers, one of which is even and the other odd, then the even number is returned. If the precision of value is less than digits, then value is returned unchanged.
The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding. If digits is zero, this kind of rounding is sometimes called rounding toward zero.
using a custom rounding
public int Round(double value)
{
double decimalpoints = Math.Abs(value - Math.Floor(value));
if (decimalpoints > 0.5)
return (int)Math.Round(value);
else
return (int)Math.Floor(value);
}
Here's the way i had to work it around :
Public Function Round(number As Double, dec As Integer) As Double
Dim decimalPowerOfTen = Math.Pow(10, dec)
If CInt(number * decimalPowerOfTen) = Math.Round(number * decimalPowerOfTen, 2) Then
Return Math.Round(number, 2, MidpointRounding.AwayFromZero)
Else
Return CInt(number * decimalPowerOfTen + 0.5) / 100
End If
End Function
Trying with 1.905 with 2 decimals will give 1.91 as expected but Math.Round(1.905,2,MidpointRounding.AwayFromZero) gives 1.90! Math.Round method is absolutely inconsistent and unusable for most of the basics problems programmers may encounter. I have to check if (int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2) cause i don not want to round up what should be round down.
This is ugly as all hell, but always produces correct arithmetic rounding.
public double ArithRound(double number,int places){
string numberFormat = "###.";
numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');
return double.Parse(number.ToString(numberFormat));
}
I am reading a Gentle Introduction to Symbolic Computation and it asks this question. Basically, the previous content deals with making up bigger functions with small ones. (Like 2- will be made of two 1- (decrement operators for lisp))
So one of the questions is what are the two different ways to define a function HALF which returns one half of its input. I have been able to come up with the obvious one (dividing number by 2) but then get stuck. I was thinking of subtracting HALF of the number from itself to get half but then the first half also has to be calculated...(I don't think the author intended to introduce recursion so soon in the book, so I am most probably wrong).
So my question is what is the other way? And are there only two ways?
EDIT : Example HALF(5) gives 2.5
P.S - the book deals with teaching LISP of which I know nothing about but apparently has a specific bent towards using smaller blocks to build bigger ones, so please try to answer using that approach.
P.P.S - I found this so far, but it is on a completely different topic - How to define that float is half of the number?
Pdf of book available here - http://www.cs.cmu.edu/~dst/LispBook/book.pdf (ctrl+f "two different ways")
It's seems to be you are describing peano arithmetic. In practice it works the same way as doing computation with fluids using cups and buckets.
You add by taking cups from the source(s) to a target bucket until the source(s) is empty. Multiplication and division is just advanced adding and substraction. To halve you take from source to two buckets in alterations until the source is empty. Of course this will either do ceil or floor depending on what bucket you choose to use as answer.
(defun halve (x)
;; make an auxillary procedure to do the job
(labels ((loop (x even acc)
(if (zerop x)
(if even (+ acc 0.5) acc)
(loop (- x 1) (not even) (if even (+ acc 1) acc)))))
;; use the auxillary procedure
(loop x nil 0)))
Originally i provided a Scheme version (since you just tagged lisp)
(define (halve x)
(let loop ((x x) (even #f) (acc 0))
(if (zero? x)
(if even (+ acc 0.5) acc)
(loop (- x 1) (not even) (if even (+ acc 1) acc)))))
Edit: Okay, lets see if I can describe this step by step. I'll break the function into multiple lines also.
(defun half (n)
;Takes integer n, returns half of n
(+
(ash n -1) ;Line A
(if (= (mod n 2) 1) .5 0))) ;Line B
So this whole function is an addition problem. It is simply adding two numbers, but to calculate the values of those two numbers requires additional function calls within the "+" function.
Line A: This performs a bit-shift on n. The -1 tells the function to shift n to the right one bit. To explain this we'll have to look at bit strings.
Suppose we have the number 8, represented in binary. Then we shift it one to the right.
1000| --> 100|0
The vertical bar is the end of the number. When we shift one to the right, the rightmost bit pops off and is not part of the number, leaving us with 100. This is the binary for 4.
We get the same value, however if we perform the shift on nine:
1001| --> 100|1
Once, again we get the value 4. We can see from this example that bit-shifting truncates the value and we need some way to account for the lost .5 on odd numbers, which is where Line B comes in.
Line B: First this line tests to see if n is even or odd. It does this by using the modulus operation, which returns the remainder of a division problem. In our case, the function call is (mod n 2), which returns the remainder of n divided by 2. If n is even, this will return 0, if it is odd, it will return 1.
Something that might be tripping you up is the lisp "=" function. It takes a conditional as its first parameter. The next parameter is the value the "=" function returns if the conditional is true, and the final parameter is what to return if the conditional is false.
So, in this case, we test to see if (mod n 2) is equal to one, which means we are testing to see if n is odd. If it is odd, we add .5 to our value from Line A, if it is not odd, we add nothing (0) to our value from Line A.
I eval a lisp expression in scratch
(+ (/ 1 2) (/ 1 2))
I got a 0.
normally it should be 1.
As Oleg points out, operators usually default to integer arithmetic unless you include floating point arguments (like 1.0).
With respect to your question about rational number support, emacs-calc (which is part of emacs) supports many number types including fractions (i.e. rational numbers), complex numbers, infinite precision integers, etc. Your code must call emacs-calc functions (instead of /, etc.) in order to use calc's arithmetic.
GNU Emacs Calc Manual:
Fractions
Index of Lisp Math Functions
Try this way
(+ (/ 1.0 2) (/ 1.0 2))
According to emacs doc
Function: / dividend divisor &rest divisors
if all the arguments are integers, then the result is an integer too.
You can read all about numbers in elisp here:
C-hig (elisp) Numbers RET
As already indicated by tripleee, it is apparent that the answer is "no".
Emacs calc has rational data type: use colon, like 1:2 == 0.5 or 5:3 == 1 + 2:3 == 1:2:3.
This way Emacs calc simplifies expressions, for example if you deal with display resolutions for 1920:1080 it prints 16:9! If you want 1440p with the 16:9 ratio: 1440 * 16:9 ⇒ 2560.
as you know single number will save in memory by following format:
(-1)^s * 1.f * 2^e:
and zero will save like that: 1.0000000000000000 * 2 ^ -126
now If I multiply it to another floating point number like 3.37 (-1) ^ 0 * 1.10101111 * 2 ^ 128
it will not 0 it reality,but in computer it will be 0 ,how and why?
As pointed out here (Wikipedia, sorry ...), there are special values for the exponent which are treated differently. If the exponent is zero, the formula for calculating the value of the number is
(-1)^s * 0.f * 2^(-126) # notice 0.f instead of 1.f for other exponents
So, a floating point zero has simply all bits set to zero (i.e. f=0, s=0, e=0). The multiplication algorithms of course have to take care of this "special" exponent and set the result to zero in this case (more specifically to +Zero or -Zero accordingly ...)
Zero is (typically) a special case in floating point representations, and in IEEE floating point, zero is represented as 0.0 * 2 ^ -126 (or whatever the exponent is—it really doesn't matter).
I'll say that the math unit of the cpu has some optimization for the "special" floating point numbers, like NaN, Infinity and 0 (and note that technically in IEEE binary fp there are two 0, a positive and a negative one) and know what to do in the three cases.
If you are interested, here http://steve.hollasch.net/cgindex/coding/ieeefloat.html there is one table that shows what happens when you sum/multiply the "special" numbers between themselves.
why: floating-point numbers set isn't continuous like R set in Math. Therefore some nubers can't be visualized correctly and rounded to the neares possible visualizable number
how: it's being rounded :)
Rounding errors. Computers are finite