var distances = new Dictionary<char, float>();
var nodes = new List<char>();
I have this line to find the smallest distance
nodes.Sort((x, y) => distances[x] - distances[y]);
When I use int it works well, but when I used float I got a message
cannot convert lambda expression to type
'System.Collections.Generic.IComparer' because it is not a
delegate type
Do you have an idea?
First off, your original program is a bad programming practice when the values are integers. It works for chars, but I would avoid this bad programming practice.
The delegate you pass to the sort function must have a number of properties; in particular it must return a negative int if x is smaller than y, a positive int if x is greater than y, and zero if they are equal. Your original lambda does not do that for integer values. (See if you can find two integers x and y such that x is smaller than y but x - y is positive.)
The delegate must also impose a total order. In a total order:
Transitivity must hold. If A == B and B == C then A must equal C. If A < B and B < C then A must be smaller than C. And so on.
It must be antisymmetric. That is, if A < B then B > A, and so on.
Subtraction does not meet these conditions in integers. The correct code is to actually write a comparison.
nodes.Sort((x, y) => x < y ? -1 : (x > y ? 1 : 0));
That then works well for chars and floats, provided there are no NaNs. If you have NaNs then you need to do extra work to impose a total order.
I would also point out that this ordinal comparison on chars is usually not the comparison you want. Sure, this will correctly note that e is smaller than z, but simple ordinal comparison also says that z is smaller than é, which is likely not what you want. Character ordering depends on culture; are you sure you want to order by the order that the Unicode committee just happened to impose?
For more on this topic see my series of articles; it begins here:
http://ericlippert.com/2011/01/20/bad-comparisons-part-one/
You can't convert your lambda expression into a Comparison<char> (which is what you want) because it returns a float - you've effectively got a Func<char, char, float> there, whereas Comparison<char> is closer to Func<char, char, int>.
The simplest approach is to use float.CompareTo:
nodes.Sort((x, y) => distances[x].CompareTo(distances[y]));
Or if you don't need to sort in-place, you could use LINQ:
var sorted = nodes.OrderBy(x => distances[x]);
Reformulate the lambda expression as follows.
nodes.Sort((x, y) =>
{
float Result = distances[x] - distances[y];
if ( Result > 0.0f )
return 1;
else if ( Result < 0.0f )
return -1;
else
return 0;
});
Related
I'm currently writing some code where I have something along the lines of:
double a = SomeCalculation1();
double b = SomeCalculation2();
if (a < b)
DoSomething2();
else if (a > b)
DoSomething3();
And then in other places I may need to do equality:
double a = SomeCalculation3();
double b = SomeCalculation4();
if (a == 0.0)
DoSomethingUseful(1 / a);
if (b == 0.0)
return 0; // or something else here
In short, I have lots of floating point math going on and I need to do various comparisons for conditions. I can't convert it to integer math because such a thing is meaningless in this context.
I've read before that floating point comparisons can be unreliable, since you can have things like this going on:
double a = 1.0 / 3.0;
double b = a + a + a;
if ((3 * a) != b)
Console.WriteLine("Oh no!");
In short, I'd like to know: How can I reliably compare floating point numbers (less than, greater than, equality)?
The number range I am using is roughly from 10E-14 to 10E6, so I do need to work with small numbers as well as large.
I've tagged this as language agnostic because I'm interested in how I can accomplish this no matter what language I'm using.
TL;DR
Use the following function instead of the currently accepted solution to avoid some undesirable results in certain limit cases, while being potentially more efficient.
Know the expected imprecision you have on your numbers and feed them accordingly in the comparison function.
bool nearly_equal(
float a, float b,
float epsilon = 128 * FLT_EPSILON, float abs_th = FLT_MIN)
// those defaults are arbitrary and could be removed
{
assert(std::numeric_limits<float>::epsilon() <= epsilon);
assert(epsilon < 1.f);
if (a == b) return true;
auto diff = std::abs(a-b);
auto norm = std::min((std::abs(a) + std::abs(b)), std::numeric_limits<float>::max());
// or even faster: std::min(std::abs(a + b), std::numeric_limits<float>::max());
// keeping this commented out until I update figures below
return diff < std::max(abs_th, epsilon * norm);
}
Graphics, please?
When comparing floating point numbers, there are two "modes".
The first one is the relative mode, where the difference between x and y is considered relatively to their amplitude |x| + |y|. When plot in 2D, it gives the following profile, where green means equality of x and y. (I took an epsilon of 0.5 for illustration purposes).
The relative mode is what is used for "normal" or "large enough" floating points values. (More on that later).
The second one is an absolute mode, when we simply compare their difference to a fixed number. It gives the following profile (again with an epsilon of 0.5 and a abs_th of 1 for illustration).
This absolute mode of comparison is what is used for "tiny" floating point values.
Now the question is, how do we stitch together those two response patterns.
In Michael Borgwardt's answer, the switch is based on the value of diff, which should be below abs_th (Float.MIN_NORMAL in his answer). This switch zone is shown as hatched in the graph below.
Because abs_th * epsilon is smaller that abs_th, the green patches do not stick together, which in turn gives the solution a bad property: we can find triplets of numbers such that x < y_1 < y_2 and yet x == y2 but x != y1.
Take this striking example:
x = 4.9303807e-32
y1 = 4.930381e-32
y2 = 4.9309825e-32
We have x < y1 < y2, and in fact y2 - x is more than 2000 times larger than y1 - x. And yet with the current solution,
nearlyEqual(x, y1, 1e-4) == False
nearlyEqual(x, y2, 1e-4) == True
By contrast, in the solution proposed above, the switch zone is based on the value of |x| + |y|, which is represented by the hatched square below. It ensures that both zones connects gracefully.
Also, the code above does not have branching, which could be more efficient. Consider that operations such as max and abs, which a priori needs branching, often have dedicated assembly instructions. For this reason, I think this approach is superior to another solution that would be to fix Michael's nearlyEqual by changing the switch from diff < abs_th to diff < eps * abs_th, which would then produce essentially the same response pattern.
Where to switch between relative and absolute comparison?
The switch between those modes is made around abs_th, which is taken as FLT_MIN in the accepted answer. This choice means that the representation of float32 is what limits the precision of our floating point numbers.
This does not always make sense. For example, if the numbers you compare are the results of a subtraction, perhaps something in the range of FLT_EPSILON makes more sense. If they are squared roots of subtracted numbers, the numerical imprecision could be even higher.
It is rather obvious when you consider comparing a floating point with 0. Here, any relative comparison will fail, because |x - 0| / (|x| + 0) = 1. So the comparison needs to switch to absolute mode when x is on the order of the imprecision of your computation -- and rarely is it as low as FLT_MIN.
This is the reason for the introduction of the abs_th parameter above.
Also, by not multiplying abs_th with epsilon, the interpretation of this parameter is simple and correspond to the level of numerical precision that we expect on those numbers.
Mathematical rumbling
(kept here mostly for my own pleasure)
More generally I assume that a well-behaved floating point comparison operator =~ should have some basic properties.
The following are rather obvious:
self-equality: a =~ a
symmetry: a =~ b implies b =~ a
invariance by opposition: a =~ b implies -a =~ -b
(We don't have a =~ b and b =~ c implies a =~ c, =~ is not an equivalence relationship).
I would add the following properties that are more specific to floating point comparisons
if a < b < c, then a =~ c implies a =~ b (closer values should also be equal)
if a, b, m >= 0 then a =~ b implies a + m =~ b + m (larger values with the same difference should also be equal)
if 0 <= λ < 1 then a =~ b implies λa =~ λb (perhaps less obvious to argument for).
Those properties already give strong constrains on possible near-equality functions. The function proposed above verifies them. Perhaps one or several otherwise obvious properties are missing.
When one think of =~ as a family of equality relationship =~[Ɛ,t] parameterized by Ɛ and abs_th, one could also add
if Ɛ1 < Ɛ2 then a =~[Ɛ1,t] b implies a =~[Ɛ2,t] b (equality for a given tolerance implies equality at a higher tolerance)
if t1 < t2 then a =~[Ɛ,t1] b implies a =~[Ɛ,t2] b (equality for a given imprecision implies equality at a higher imprecision)
The proposed solution also verifies these.
Comparing for greater/smaller is not really a problem unless you're working right at the edge of the float/double precision limit.
For a "fuzzy equals" comparison, this (Java code, should be easy to adapt) is what I came up with for The Floating-Point Guide after a lot of work and taking into account lots of criticism:
public static boolean nearlyEqual(float a, float b, float epsilon) {
final float absA = Math.abs(a);
final float absB = Math.abs(b);
final float diff = Math.abs(a - b);
if (a == b) { // shortcut, handles infinities
return true;
} else if (a == 0 || b == 0 || diff < Float.MIN_NORMAL) {
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
return diff < (epsilon * Float.MIN_NORMAL);
} else { // use relative error
return diff / (absA + absB) < epsilon;
}
}
It comes with a test suite. You should immediately dismiss any solution that doesn't, because it is virtually guaranteed to fail in some edge cases like having one value 0, two very small values opposite of zero, or infinities.
An alternative (see link above for more details) is to convert the floats' bit patterns to integer and accept everything within a fixed integer distance.
In any case, there probably isn't any solution that is perfect for all applications. Ideally, you'd develop/adapt your own with a test suite covering your actual use cases.
I had the problem of Comparing floating point numbers A < B and A > B
Here is what seems to work:
if(A - B < Epsilon) && (fabs(A-B) > Epsilon)
{
printf("A is less than B");
}
if (A - B > Epsilon) && (fabs(A-B) > Epsilon)
{
printf("A is greater than B");
}
The fabs--absolute value-- takes care of if they are essentially equal.
We have to choose a tolerance level to compare float numbers. For example,
final float TOLERANCE = 0.00001;
if (Math.abs(f1 - f2) < TOLERANCE)
Console.WriteLine("Oh yes!");
One note. Your example is rather funny.
double a = 1.0 / 3.0;
double b = a + a + a;
if (a != b)
Console.WriteLine("Oh no!");
Some maths here
a = 1/3
b = 1/3 + 1/3 + 1/3 = 1.
1/3 != 1
Oh, yes..
Do you mean
if (b != 1)
Console.WriteLine("Oh no!")
Idea I had for floating point comparison in swift
infix operator ~= {}
func ~= (a: Float, b: Float) -> Bool {
return fabsf(a - b) < Float(FLT_EPSILON)
}
func ~= (a: CGFloat, b: CGFloat) -> Bool {
return fabs(a - b) < CGFloat(FLT_EPSILON)
}
func ~= (a: Double, b: Double) -> Bool {
return fabs(a - b) < Double(FLT_EPSILON)
}
Adaptation to PHP from Michael Borgwardt & bosonix's answer:
class Comparison
{
const MIN_NORMAL = 1.17549435E-38; //from Java Specs
// from http://floating-point-gui.de/errors/comparison/
public function nearlyEqual($a, $b, $epsilon = 0.000001)
{
$absA = abs($a);
$absB = abs($b);
$diff = abs($a - $b);
if ($a == $b) {
return true;
} else {
if ($a == 0 || $b == 0 || $diff < self::MIN_NORMAL) {
return $diff < ($epsilon * self::MIN_NORMAL);
} else {
return $diff / ($absA + $absB) < $epsilon;
}
}
}
}
You should ask yourself why you are comparing the numbers. If you know the purpose of the comparison then you should also know the required accuracy of your numbers. That is different in each situation and each application context. But in pretty much all practical cases there is a required absolute accuracy. It is only very seldom that a relative accuracy is applicable.
To give an example: if your goal is to draw a graph on the screen, then you likely want floating point values to compare equal if they map to the same pixel on the screen. If the size of your screen is 1000 pixels, and your numbers are in the 1e6 range, then you likely will want 100 to compare equal to 200.
Given the required absolute accuracy, then the algorithm becomes:
public static ComparisonResult compare(float a, float b, float accuracy)
{
if (isnan(a) || isnan(b)) // if NaN needs to be supported
return UNORDERED;
if (a == b) // short-cut and takes care of infinities
return EQUAL;
if (abs(a-b) < accuracy) // comparison wrt. the accuracy
return EQUAL;
if (a < b) // larger / smaller
return SMALLER;
else
return LARGER;
}
The standard advice is to use some small "epsilon" value (chosen depending on your application, probably), and consider floats that are within epsilon of each other to be equal. e.g. something like
#define EPSILON 0.00000001
if ((a - b) < EPSILON && (b - a) < EPSILON) {
printf("a and b are about equal\n");
}
A more complete answer is complicated, because floating point error is extremely subtle and confusing to reason about. If you really care about equality in any precise sense, you're probably seeking a solution that doesn't involve floating point.
I tried writing an equality function with the above comments in mind. Here's what I came up with:
Edit: Change from Math.Max(a, b) to Math.Max(Math.Abs(a), Math.Abs(b))
static bool fpEqual(double a, double b)
{
double diff = Math.Abs(a - b);
double epsilon = Math.Max(Math.Abs(a), Math.Abs(b)) * Double.Epsilon;
return (diff < epsilon);
}
Thoughts? I still need to work out a greater than, and a less than as well.
I came up with a simple approach to adjusting the size of epsilon to the size of the numbers being compared. So, instead of using:
iif(abs(a - b) < 1e-6, "equal", "not")
if a and b can be large, I changed that to:
iif(abs(a - b) < (10 ^ -abs(7 - log(a))), "equal", "not")
I suppose that doesn't satisfy all the theoretical issues discussed in the other answers, but it has the advantage of being one line of code, so it can be used in an Excel formula or an Access query without needing a VBA function.
I did a search to see if others have used this method and I didn't find anything. I tested it in my application and it seems to be working well. So it seems to be a method that is adequate for contexts that don't require the complexity of the other answers. But I wonder if it has a problem I haven't thought of since no one else seems to be using it.
If there's a reason the test with the log is not valid for simple comparisons of numbers of various sizes, please say why in a comment.
You need to take into account that the truncation error is a relative one. Two numbers are about equal if their difference is about as large as their ulp (Unit in the last place).
However, if you do floating point calculations, your error potential goes up with every operation (esp. careful with subtractions!), so your error tolerance needs to increase accordingly.
The best way to compare doubles for equality/inequality is by taking the absolute value of their difference and comparing it to a small enough (depending on your context) value.
double eps = 0.000000001; //for instance
double a = someCalc1();
double b = someCalc2();
double diff = Math.abs(a - b);
if (diff < eps) {
//equal
}
I have two arrays
double[] a = new double[] {1,2,3,4,5};
double[] b = new double[] {2,3,2,3,5};
which I convert into two vectors:
Vector<double> A = Vector<double>.Build.DenseOfArray(a);
Vector<double> B = Vector<double>.Build.DenseOfArray(b);
I would like to compare the values of 'A' against 'B' and return a vector where elements 2 and 3 (0,1,2,3,4) are clipped because they are greater than the equivalent value in 'b' e.g:
[1,2,2,3,5]
Can anyone explain how to do this without resorting to a for loop?
Looks like the Map2 method can do what you want. From the documentation:
Vector<T> Map2(Func<T, T, T> f, Vector<T> other, Zeros zeros)
Applies a function to each value pair of two vectors and returns the results as a new vector.
Note that the third parameter is actually optional and has a default value of Zeros.AllowSkip.
You can use the method like this:
Vector<double> C = A.Map2((x, y) => (x > y ? y : x), B);
Demo fiddle: https://dotnetfiddle.net/hfWJhI
finalResult = Math.Ceiling(result = (x - y) / (z - 1));
I am trying to get whole rounded number. finalResult and result are double. Others are int. And well... not working.
I would appreciate some help. Thank you.
In order to get the result of this operation as double you have to make at least one operand double (see https://msdn.microsoft.com/en-us/library/3t4w2bkb.aspx). Try adding 'd' to literal:
finalResult = Math.Ceiling(result = (x - y) / (z - 1d));
By doing this little trick you ensure that '1' will be treated as double, not as int, so the whole operation outcome will be a double.
Note: Unless you want to round this value up, you should change the rounding method to Math.Round().
Note 2: Make sure to prevent division by 0 by checking if(z != 0).
Since x, y and z are all int, then the division will be done as integer and will be truncated.
To avoid that, simply cast like so:
finalResult = Math.Ceiling(result = (x - y) / (double)(z - 1));
(I'm assuming here you want to round up, so if the result of the division was, say, 1.00001, you'd want the rounded result to be 2.0.)
You need a type casting to get Math.Ceiling to work.
Decimal finalResult = Math.Ceiling(((Decimal)(x - y)) / (z - 1));
My brain seems to be in masochistic mode, so after being drowned in this, this and this, it wanted to mess around with some DIY in C#.
I came up with the following, which I don't think is the Y-combinator, but it does seem to manage to make a non-recursive function recursive, without referring to itself:
Func<Func<dynamic, dynamic>, Func<dynamic, dynamic>> Y = x => x(x);
So given these:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(self)(n - 1);
Func<dynamic, Func<dynamic, dynamic>> fib =
self => n => n < 2 ? n : self(self)(n-1) + self(self)(n-2);
We can generate these:
Func<dynamic, dynamic> Fact = Y(fact);
Func<dynamic, dynamic> Fib = Y(fib);
Enumerable.Range(0, 10)
.ToList()
.ForEach(i => Console.WriteLine("Fact({0})={1}", i, Fact(i)));
Enumerable.Range(0, 10)
.ToList()
.ForEach(i => Console.WriteLine("Fib({0})={1}", i, Fib(i)));
No, that's not the Y combinator; you're only halfway there. You still need to factor out the self-application within the "seed" functions you're applying it to. That is, instead of this:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(self)(n - 1);
you should have this:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(n - 1);
Note the single occurrence of self in the second definition as opposed to the two occurrences in the first definition.
(edited to add:) BTW, since your use of C# simulates the lambda calculus with call-by-value evaluation, the fixed-point combinator you want is the one often called Z, not Y
(edited again to elaborate:) The equation that describes Y is this (see the wikipedia page for the derivation):
Y g = g (Y g)
But in most practical programming languages, you evaluate the argument of a function before you call the function. In the programming languages community, that's called call-by-value evaluation (not to be confused with the way C/C++/Fortran/etc programmers distinguish "call by value" vs "call by reference" vs "call by copy-restore", etc).
But if we did that, we'd get
Y g = g (Y g) = g (g (Y g)) = g (g (g (Y g))) = ...
That is, we'd spend all of our time constructing the recursive function and never get around to applying it.
In call-by-name evaluation, on the other hand, you apply a function, here g, to the unevaluated argument expression, here (Y g). But if g is like fact, it's waiting for another argument before it does anything. So we would wait for the second argument to g before trying to evaluate (Y g) further---and depending on what the function does (ie, if it has a base case), we might not need to evaluate (Y g) at all. That's why Y works for call-by-name evaluation.
The fix for call-by-value is to change the equation. Instead of Y g = g (Y g), we want something like the following equation instead:
Z g = g (λx. (Z g) x)
(I think I got the equation right, or close to right. You can calculate it out and see if it fits with the definition of Z.)
One way to think of this is instead of computing "the whole recursive function" and handing it to g, we hand it a function that will compute the recursive function a little bit at a time---and only when we actually need a bit more of it so we can apply it to an argument (x).
Background:
I was "dragged" into seeing this question:
Fibonacci's Closed-form expression in Haskell
when the author initially tagged with many other languages but later focused to a Haskell question. Unfortunately I have no experience whatsoever with Haskell so I couldn't really participate in the question. However one of the answers caught my eye where the answerer turned it into a pure integer math problem. That sounded awesome to me so I had to figure out how it worked and compare this to a recursive Fibonacci implementation to see how accurate it was. I have a feeling that if I just remembered the relevant math involving irrational numbers, I might be able to work everything out myself (but I don't). So the first step for me was to port it to a language I am familiar with. In this case, I am doing C#.
I am not completely in the dark fortunately. I have plenty experience in another functional language (OCaml) so a lot of it looked somewhat familiar to me. Starting out with the conversion, everything seemed straightforward since it basically defined a new numeric type to help with the calculations. However I've hit a couple of roadblocks in the translation and am having trouble finishing it. I'm getting completely wrong results.
Analysis:
Here's the code that I'm translating:
data Ext = Ext !Integer !Integer
deriving (Eq, Show)
instance Num Ext where
fromInteger a = Ext a 0
negate (Ext a b) = Ext (-a) (-b)
(Ext a b) + (Ext c d) = Ext (a+c) (b+d)
(Ext a b) * (Ext c d) = Ext (a*c + 5*b*d) (a*d + b*c) -- easy to work out on paper
-- remaining instance methods are not needed
fib n = divide $ twoPhi^n - (2-twoPhi)^n
where twoPhi = Ext 1 1
divide (Ext 0 b) = b `div` 2^n -- effectively divides by 2^n * sqrt 5
So based on my research and what I can deduce (correct me if I'm wrong anywhere), the first part declares type Ext with a constructor that will have two Integer parameters (and I guess will inherit the Eq and Show types/modules).
Next is the implementation of Ext which "derives" from Num. fromInteger performs a conversion from an Integer. negate is the unary negation and then there's the binary addition and multiplication operators.
The last part is the actual Fibonacci implementation.
Questions:
In the answer, hammar (the answerer) mentions that exponentiation is handled by the default implementation in Num. But what does that mean and how is that actually applied to this type? Is there an implicit number "field" that I'm missing? Does it just apply the exponentiation to each corresponding number it contains? I assume it does the latter and end up with this C# code:
public static Ext operator ^(Ext x, int p) // "exponent"
{
// just apply across both parts of Ext?
return new Ext(BigInt.Pow(x.a, p), BigInt.Pow(x.b, p));
// Ext (a^p) (b^p)
}
However this conflicts with how I perceive why negate is needed, it wouldn't need it if this actually happens.
Now the meat of the code. I read the first part divide $ twoPhi^n - (2-twoPhi)^n as:
divide the result of the following expression: twoPhi^n - (2-twoPhi)^n.
Pretty simple. Raise twoPhi to the nth power. Subtract from that the result of the rest. Here we're doing binary subtraction but we only implemented unary negation. Or did we not? Or can binary subtraction be implied because it could be made up combining addition and negation (which we have)? I assume the latter. And this eases my uncertainty about the negation.
The last part is the actual division: divide (Ext 0 b) = b `div` 2^n. Two concerns here. From what I've found, there is no division operator, only a `div` function. So I would just have to divide the numbers here. Is this correct? Or is there a division operator but a separate `div` function that does something else special?
I'm not sure how to interpret the beginning of the line. Is it just a simple pattern match? In other words, would this only apply if the first parameter was a 0? What would the result be if it didn't match (the first was non-zero)? Or should I be interpreting it as we don't care about the first parameter and apply the function unconditionally? This seems to be the biggest hurdle and using either interpretation still yields the incorrect results.
Did I make any wrong assumptions anywhere? Or is it all right and I just implemented the C# incorrectly?
Code:
Here's the (non-working) translation and the full source (including tests) so far just in case anyone is interested.
// code removed to keep post size down
// full source still available through link above
Progress:
Ok so looking at the answers and comments so far, I think I know where to go from here and why.
The exponentiation just needed to do what it normally does, multiply p times given that we've implemented the multiply operation. It never crossed my mind that we should do what math class has always told us to do. The implied subtraction from having addition and negation is a pretty handy feature too.
Also spotted a typo in my implementation. I added when I should have multiplied.
// (Ext a b) * (Ext c d) = Ext (a*c + 5*b*d) (a*d + b*c)
public static Ext operator *(Ext x, Ext y)
{
return new Ext(x.a * y.a + 5*x.b*y.b, x.a*y.b + x.b*y.a);
// ^ oops!
}
Conclusion:
So now it's completed. I only implemented to essential operators and renamed it a bit. Named in a similar manner as complex numbers. So far, consistent with the recursive implementation, even at really large inputs. Here's the final code.
static readonly Complicated TWO_PHI = new Complicated(1, 1);
static BigInt Fib_x(int n)
{
var x = Complicated.Pow(TWO_PHI, n) - Complicated.Pow(2 - TWO_PHI, n);
System.Diagnostics.Debug.Assert(x.Real == 0);
return x.Bogus / BigInt.Pow(2, n);
}
struct Complicated
{
private BigInt real;
private BigInt bogus;
public Complicated(BigInt real, BigInt bogus)
{
this.real = real;
this.bogus = bogus;
}
public BigInt Real { get { return real; } }
public BigInt Bogus { get { return bogus; } }
public static Complicated Pow(Complicated value, int exponent)
{
if (exponent < 0)
throw new ArgumentException(
"only non-negative exponents supported",
"exponent");
Complicated result = 1;
Complicated factor = value;
for (int mask = exponent; mask != 0; mask >>= 1)
{
if ((mask & 0x1) != 0)
result *= factor;
factor *= factor;
}
return result;
}
public static implicit operator Complicated(int real)
{
return new Complicated(real, 0);
}
public static Complicated operator -(Complicated l, Complicated r)
{
var real = l.real - r.real;
var bogus = l.bogus - r.bogus;
return new Complicated(real, bogus);
}
public static Complicated operator *(Complicated l, Complicated r)
{
var real = l.real * r.real + 5 * l.bogus * r.bogus;
var bogus = l.real * r.bogus + l.bogus * r.real;
return new Complicated(real, bogus);
}
}
And here's the fully updated source.
[...], the first part declares type Ext with a constructor that will have two Integer parameters (and I guess will inherit the Eq and Show types/modules).
Eq and Show are type classes. You can think of them as similar to interfaces in C#, only more powerful. deriving is a construct that can be used to automatically generate implementations for a handful of standard type classes, including Eq, Show, Ord and others. This reduces the amount of boilerplate you have to write.
The instance Num Ext part provides an explicit implementation of the Num type class. You got most of this part right.
[the answerer] mentions that exponentiation is handled by the default implementation in Num. But what does that mean and how is that actually applied to this type? Is there an implicit number "field" that I'm missing? Does it just apply the exponentiation to each corresponding number it contains?
This was a bit unclear on my part. ^ is not in the type class Num, but it is an auxilliary function defined entirely in terms of the Num methods, sort of like an extension method. It implements exponentiation to positive integral powers through binary exponentiation. This is the main "trick" of the code.
[...] we're doing binary subtraction but we only implemented unary negation. Or did we not? Or can binary subtraction be implied because it could be made up combinding addition and negation (which we have)?
Correct. The default implementation of binary minus is x - y = x + (negate y).
The last part is the actual division: divide (Ext 0 b) = b `div` 2^n. Two concerns here. From what I've found, there is no division operator, only a div function. So I would just have to divide the numbers here. Is this correct? Or is there a division operator but a separate div function that does something else special?
There is only a syntactic difference between operators and functions in Haskell. One can treat an operator as a function by writing it parenthesis (+), or treat a function as a binary operator by writing it in `backticks`.
div is integer division and belongs to the type class Integral, so it is defined for all integer-like types, including Int (machine-sized integers) and Integer (arbitrary-size integers).
I'm not sure how to interpret the beginning of the line. Is it just a simple pattern match? In other words, would this only apply if the first parameter was a 0? What would the result be if it didn't match (the first was non-zero)? Or should I be interpreting it as we don't care about the first parameter and apply the function unconditionally?
It is indeed just a simple pattern match to extract the coefficient of √5. The integral part is matched against a zero to express to readers that we indeed expect it to always be zero, and to make the program crash if some bug in the code was causing it not to be.
A small improvement
Replacing Integer with Rational in the original code, you can write fib n even closer to Binet's formula:
fib n = divSq5 $ phi^n - (1-phi)^n
where divSq5 (Ext 0 b) = numerator b
phi = Ext (1/2) (1/2)
This performs the divisions throughout the computation, instead of saving it all up for the end. This results in smaller intermediate numbers and about 20% speedup when calculating fib (10^6).
First, Num, Show, Eq are type classes, not types nor modules. They are a bit similar to interfaces in C#, but are resolved statically rather than dynamically.
Second, exponentiation is performed via multiplication with the implementation of ^, which is not a member of the Num typeclass, but a separate function.
The implementation is the following:
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0 = error "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0 ^ y0 = x ^ y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) ((y - 1) `quot` 2) x
-- g : x0 ^ y0 = (x ^ y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) ((y - 1) `quot` 2) (x * z)
This seems to be the missing part of solution.
You are right about subtraction. It is implemented via addition and negation.
Now, the divide function divides only if a equals to 0. Otherwise we get a pattern match failure, indicating a bug in the program.
The div function is a simple integer division, equivalent to / applied to integral types in C#. There is also an operator / in Haskell, but it indicates real number division.
A quick implementation in C#. I implemented exponentiation using the square-and-multiply algorithm.
It is enlightening to compare this type which has the form a+b*Sqrt(5) with the complex numbers which take the form a+b*Sqrt(-1). Addition and subtraction work just the same. Multiplication is slightly different, because i^2 isn't -1 but +5 here. Division is slightly more complicated, but shouldn't be too hard either.
Exponentiation is defined as multiplying a number with itself n times. But of course that's slow. So we use the fact that ((a*a)*a)*a is identical to (a*a)*(a*a) and rewrite using the square-and-multiply algorithm. So we just need log(n) multiplications instead of n multiplications.
Just calculating the exponential of the individual components doesn't work. That's because the matrix underlying your type isn't diagonal. Compare this to the property of complex numbers. You can't simply calculate the exponential of the real and imaginary part separately.
struct MyNumber
{
public readonly BigInteger Real;
public readonly BigInteger Sqrt5;
public MyNumber(BigInteger real,BigInteger sqrt5)
{
Real=real;
Sqrt5=sqrt5;
}
public static MyNumber operator -(MyNumber left,MyNumber right)
{
return new MyNumber(left.Real-right.Real, left.Sqrt5-right.Sqrt5);
}
public static MyNumber operator*(MyNumber left,MyNumber right)
{
BigInteger real=left.Real*right.Real + left.Sqrt5*right.Sqrt5*5;
BigInteger sqrt5=left.Real*right.Sqrt5 + right.Real*left.Sqrt5;
return new MyNumber(real,sqrt5);
}
public static MyNumber Power(MyNumber b,int exponent)
{
if(!(exponent>=0))
throw new ArgumentException();
MyNumber result=new MyNumber(1,0);
MyNumber multiplier=b;
while(exponent!=0)
{
if((exponent&1)==1)//exponent is odd
result*=multiplier;
multiplier=multiplier*multiplier;
exponent/=2;
}
return result;
}
public override string ToString()
{
return Real.ToString()+"+"+Sqrt5.ToString()+"*Sqrt(5)";
}
}
BigInteger Fibo(int n)
{
MyNumber num = MyNumber.Power(new MyNumber(1,1),n)-MyNumber.Power(new MyNumber(1,-1),n);
num.Dump();
if(num.Real!=0)
throw new Exception("Asser failed");
return num.Sqrt5/BigInteger.Pow(2,n);
}
void Main()
{
MyNumber num=new MyNumber(1,2);
MyNumber.Power(num,2).Dump();
Fibo(5).Dump();
}