This is in both common lisp (clisp and sbcl) and scheme (guile). While these are true:
(= 1/2 0.5)
(= 1/4 0.25)
This turns out to be false:
(= 1/5 0.2)
I checked the hyperspec, it says that "=" should check for mathematical equivalency despite the types of the arguments. What the heck is going on?
The problem is that 0.2 really is not equal to 1/5. Floating point numbers cannot represent 0.2 correctly, so the literal 0.2 is actually rounded to the nearest representable floating point number (0.200000001 or something like that). After this rounding occurs, the computer has no way of knowing that your number was originally 0.2 and not another nearby non-representable number (such as 0.20000000002).
As for the reason why 1/2 and 1/4 work its because floating point is a base 2 encoding and can accurately represent powers of two.
please read What every Computer Scientist should know about Floating Point Numbers
This actually depends on what is coerced to what. If you think about it, then rational is more precise, so it makes sense to coerce to rational for comparison, rather then to float, however, if you consciously want to compare numbers as being floats you can force it by doing something like below:
(declaim (inline float=))
(defun float= (a b)
(= (coerce a 'float) (coerce b 'float)))
(float= 0.2 1/5) ; T
Actually... there's more to it, since floats provide you with things like not-a-number, positive-infinity and negative-infinity. Infinities, for example, for the 64-bit floats are 10e200 iirc, so, there's nothing stopping you from creating a rational larger then infinity (or smaller then negative infinity!), so, perhaps, if you want to be super precise, you'd need to consider those cases too. Likewise a comparison to not-a-number must always give you nil...
However, in scheme you have exact numbers, so you may ask (note the #e prefix, which means the number which follows is to be treated exactly):
> (= 1/5 #e0.2)
#t
Related
As any secondary math student can attest, pi is irrational.
And yet:
Welcome to Racket v5.3.6.
> pi
3.141592653589793
> (rational? pi)
#t
Is this because the representation of pi, in the underlying machine's floating point format, is of limited precision and therefore can always be expressed as some p/q where q is 10^n, and n is the representational precision ?
If so, how could any number thrown about by Racket (or other similarly-behaving scheme) ever be considered anything but rational? And hence, why bother with the rational? function?
UPDATE: Even (rational? (sqrt 3)) reports #t
The number returned by pi is rational because the documentation says so. Specifically it says:
All numbers are complex numbers. Some of them are real numbers, and all of the real numbers that can be represented are also rational numbers, except for +inf.0 (positive infinity), +inf.f (single-precision variant), -inf.0 (negative infinity), -inf.f (single-precision variant), +nan.0 (not-a-number), and +nan.f (single-precision variant). Among the rational numbers, some are integers, because round applied to the number produces the same number.
So your hunch is right. All representable real numbers are indeed rational (except for the infinities and NaNs) because, yes, numbers are stored in fixed-size registers so the machine isn't going to store an irrational number.
As to why the Racket designers bothered with a rational? function, that is a good question. Many languages like Julia and Clojure have a real, actual, honest-to-goodness rational datatype. Racket doesn't, so, as you suspect, it does seem silly to define a near-complete subset of the reals as rationals.
But you know, it just may be convenient to have a way to talk about a non-NaN, non-Infinity value. I would have called it finite, but Racket calls it rational.
I have to run some computations in Racket that I have never used before.
How do I force it to calculate sth in single or half (if it has those) precision floats?
I figured out how to make it compute in big floats:
(bf/ (bf 1) (bf 7))
I know that the abbreviation for floats (double precision) is fl. I cannot figure out the right abbreviation for single floats though.
The 'bigfloat' package you refer to are for arbitrary precision floating point numbers. You're very unlikely to want these, as you point out.
It sounds like you're looking for standard IEEE 64-bit floating point numbers. Racket uses these by default, for all inexact arithmetic.
So, for instance:
(/ 1 pi)
produces
0.3183098861837907
One possible tripper-upper is that when dividing two rational numbers, the result will again be a rational number. So, for instance,
(/ 12347728 298340194)
produces
6173864/149170097
You can force inexact arithmetic either by using exact->inexact (always works), or by ensuring that your literals end with decimals (unless you're using the htdp languages).
So, for instance:
(/ 12347728.0 298340194.0)
produces
0.04138808061511148
Let me know if this doesn't answer your question....
In MATLAB the following is true
0.1 * 10.0 == 1
But 0.1 is not represented exactly in floating point, so I expected it to not be true. Did I just get lucky and the error happened to be smaller than eps, so it got rounded to 1?
MATLAB implements IEEE 754, so I think it should apply to all languages. But this post makes me think it might be something specific to MATLAB.
Your specific example is true for any language which uses IEEE754 floating point arithmetic (well, 64-bit at least).
The literal 0.1 is exactly
0.1000000000000000055511151231257827021181583404541015625
10.0 is exactly 10
Their product is therefore
1.000000000000000055511151231257827021181583404541015625
The two closest floating point values are:
1.0
1.000000000000000222044604925031308084726333618164062
of which the first is closest, so the result is rounded to that.
(I'm not 100% sure what is going on in that example you link to: I suspect it has to do with C# using higher intermediate precision)
In general, however, this sort of thing isn't true. e.g. 0.51255*1e5 isn't 51255 (though MATLAB may lie when printing, try 0.51255*1e5-51255).
I have learning Common Lisp for 2 months, I meet a puzzle, here is the code:
CL-USER> (round 33.6)
34
-0.40000153
anyone explain it? Thanks
I'm not sure I understand your problem. In CLisp, round rounds to the nearest integer (unless you specify a divisor). The nearest integer to 33.6 is 34 so that bit is right.
And since round returns both the quotient and remainder, it gives 34, with a remainder of -0.4. That bit's mostly right so I suspect you're wondering why it's only "mostly".
The reason it's not exactly -0.4 is almost certainly due to the limited precision of floating point numbers. The result of calculating the difference between a (seemingly exact) floating point number and an integer can be surprising:
CL-USER> (- 23.6 24) -0.39999962
You'd expect in a perfect world for that to return -0.4 but it doesn't, for reasons mentioned above.
If you want to know why that's the case (i.e., how floating point works under the covers), you can check out this and this as examples.
Is there official documentation to resolve the apparent conflict between these two statements from the NetLogo 5.0.5 Programming Guide:
"A patch's coordinates are always integers" (from the Agents section)
"All numbers in NetLogo are stored internally as double precision floating point numbers" (from the Math section on the same page.)
Here's why I ask: if the integer patch coordinates are stored as floating point numbers that are very close to integer values then I should avoid comparisons for equality. For example, if there are really no integers, instead of
if pxcor = pycor...
I should use the usual tolerance-checking, like
if abs( pxcor – pycor) < 0.1 ...
Is there some official word that the more complicated code is unnecessary?
The Math section also seems to imply the absence of integer literals: "No distinction is made between 3 and 3.0". So is the official policy to avoid comparisons for equality with constants? For example, is there official sanction for writing code like
if pxcor = 3...
?
Are sliders defined somewhere to produce floating point values? If so, it seems invalid to compare slider values for equality, also. That is, if so, one should avoid writing code like
if pxcor = slider-value
even when the minimum, maximum, and increment values for the slider look like integers.
The focus on official sources in this question arises because I'm not just trying to write a working program. Rather, I'm seeking to tell students how they should program. I'd hate to mislead them, so thanks for any good advice.
NetLogo isn't the only language that works this way, with all numbers stored internally as double precision floating point. The best known other such language is JavaScript.
Math in NetLogo follows IEEE 754, so what follows isn't actually specific to NetLogo, but applies to IEEE 754 generally.
There's no contradiction in the User Manual because mathematically, some floating point numbers are integers, exactly. If the fractional part is exactly zero, then mathematically, it's an integer, and IEEE 754 guarantees that arithmetic and comparison operations will behave as you would expect. If you add 2 and 2 you'll always get 4, never 3.999... or 4.00...01. Integers in, integers out. That holds for comparison, addition, subtraction, multiplication, and divisions that divide evenly. (It may not hold for other operations, so e.g. log 1000 10 isn't exactly 3, and cos 90 isn't exactly 0.)
Therefore if pxcor = 3 is completely valid, correct code. pxcor never has a fractional part, and 3 doesn't have one, either, so no issue of floating point imprecision can arise.
As for NetLogo sliders, if the slider's min, max, and increment are all integers, then there's nothing to worry about; the value of the slider is also always an integer.
(Note: I am the lead developer of NetLogo, and I wrote the sections of the User Manual that you are quoting.)
Just to stress what Seth writes:
Integers in, integers out. That holds for comparison, addition,
subtraction, multiplication, and divisions that divide evenly (emphasis added).
Here's a classic instance of floating point imprecision:
observer> show (2 + 1) / 10
observer: 0.3
observer> show 2 / 10 + 1 / 10
observer: 0.30000000000000004
For nice links that explain why, check out http://0.30000000000000004.com/