Operator overload -- Factorials (C++)

Started by Dilbert, March 28, 2007, 11:33:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dilbert

This isn't the solution I wanted to this problem, but it's pretty darn close, and it's easy to use.

What I have here is a header (.hpp) written in C++. It overloads the ! operator to allow factorials in your programs. This way, you don't have to write out the algorithm -- it's done for you and can be used almost as easily as the increment (++) operator.

For those who don't know, a factorial is the product of all integers leading up to that number. For example, 4! is 1 * 2 * 3 * 4, and 5! is 1 * 2 * 3 * 4 * 5.

The operator overload doesn't have a postfix in this case. I've created a class A that you can pass integers in. It is used like this:
!A()

where in the () is any legal integer or variable.

For example, to set x to factorial 5:
int x = !A(5);

To set something to the factorial of itself:
x = !A(x);

I apologize; I wasn't able to get something as tidy as "5!" as an expression. If anyone does, I'd appreciate it if they would share.

The actual working code is as follows:

class A
{
public:
    A::A(int x): theVal(x) {}
    int operator!();
private:
    int theVal;
};

int A::operator!()
{
    unsigned long int theFactorial = 1;
    for(int i = 1; i <= theVal; i++)
    {
        theFactorial *= i;
    }
    return theFactorial;
}
   


That's it, really. :) You then #include "factorial.hpp" into any .cpp file, and it's there for your coding purposes. All the syntax info is repeated in the .hpp file as a comment block, for easy access. A couple of notes also mentioned in the .cpp file:

Note that I use an unsigned long int for the actual factorial work. Factorials add up very fast. !A(16) is the limit for this header; anything higher causes it to display the bit value equivalent, which isn't what you want (it appears as a very large negative number).

This limit can be extended by changing all ints to doubles. However, then !A(10) and above gives answers similar to 12256+e26, and is therefore not desirable. (If you don't know why !A(17) is too much for a unsigned long, try it: 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 is a BIG number. How Calculator does it, I have no idea.)

Attached is the header file for C++, and a sample program that uses it, which I used to test my header. Enjoy. :)

[old attachment deleted by admin]
[center][/center]"The geek shall inherit the Earth."

Neil

Nice work :)

I hate being all negative, but I actually thing using the ! operating isn't a good idea. People might confuse it with its logical meaning, that is to invert a function. Simply calling the function fract() or something would be just as good.

You could try creating a number class, which contains a variable for the number, and methods for factorials and stuff.

Also try looking into macros. You might be able to use them to gt 4! to your desired meaning... I'll research it later for you. But I'm not sure it'll get it exactly like that.

Dilbert

Inverting a function? I am aware that != is used as "not equalt o" but I've never heard of inversing a function with a ! in C++. If you can find something better than this, please post it. I've done the best I can with my knowledge, but I'd love to see a x!. :)
[center][/center]"The geek shall inherit the Earth."

Neil

Inverting might not be the correct word. ! makes true into false and false into true. It is called NOT. For example (!a == b) is the same as (a != b).

My functions which do stuff, but would normally be void, I often make boolean and return whether they have been successful or not. For example, in my Noughts and Crosses game (Tic Tac Toe) I have a makemove(int x, int y) function. It returns true if the move was completed, or false if not (illegal move). So I can do this: if (!makemove(x, y)) {...request new move...} for example.

In my AI algorithim, it goes through the following stages: Can I make 3 in a row and win? Can I block a 3 in a row the opponent is about to make? *uses evaluation function to find good square*. If all else fails, move randomly. I have a boolean, foundmove, to track whether it has found a move, and stop the process, or to continue to the next stage. For example,   if (!foundmove) nextstage(); . This is the same as (foundmove != true) or (foundmove == false) but provides a shorthand way of doing it.

The point I was trying to make was, using ! in your fractorial function, might be confusing if it is used as a boolean NOT else where in the program. To someone who is unaware of what A does, it might seem like A returns a boolean, and you want to take the inverse of that result into x.

Dilbert

I see what you mean. That's why I mentioned that the user will want to make a comment or two to that effect, but it would be easier if one could just to 5! or something like that.

Trouble is, I can't think of an operator to overload that wouldn't cause confusion in some way. So if there's a way to circumvent this problem I'd love to have it; it'll make this that much easier.
[center][/center]"The geek shall inherit the Earth."

Neil

#define factorial(val) \
unsigned long limit = val; \
val = 1; \
for (unsigned long i = 1; i <= limit; i++) \
val *= i;


This fufils a similar role, and macros are faster than functions. Well, only because they don't need to copy in or return values. So since most of the processing work is done inside the macro/function it doesn't really matter. Still, it's the principle. I don't think it's possible to use the ! charecter as a macro or function name.

Dilbert

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

unsigned long int factorial = 1; //Global Variable used for the fatorial procedure.
int i;
#define FACTORIAL(x) \
        for(i = 1; i <= reply; i++) \
{ \
    factorial *= i; \
} \

#define ever ;;

int main()
{
    for(ever)
    {
        ::factorial = 1;
        cout << "Enter an integer: ";
        int reply;
        cin >> reply;
        FACTORIAL(reply);
        cout << reply << "! = " << factorial << endl << endl;
    }
    return 0;
}


I like this one; it accepts much more than the other solution did, going as high as 33! without problems. Looking back on my code, for some reason after 16 I get the negative of the correct answer, so I need to go back over that. I truly do like this better. :)
[center][/center]"The geek shall inherit the Earth."

Dilbert

typedef unsigned long int ULONG;
class A
{
public:
    A::A(int x): theVal(x) {}
    ULONG operator!();
private:
    ULONG theVal;
};

ULONG A::operator!()
{
    ULONG theFactorial = 1;
    for(int i = 1; i <= theVal; i++)
    {
        theFactorial *= i;
    }
    return theFactorial;
}


#include <iostream>
#include "factorial.hpp"
using std::cout;
using std::cin;
using std::endl;

//NOTE: !A(variable || number) is factorial, NOT the "not" modifier.
int main()
{
    cout << "Enter an integer: " << endl;
    ULONG input;
    cin >> input;
    ULONG x = !A(input);
    cout << input << " factorial is " << x << endl;
    return 0;
}


This is the original program, revamped. It has all integers re-done as ULONG, which is typedef'd as unsigned long int. The program accepts up to 33! before returning 0.

However, I still like the macro better; it's smaller and easier to read. Too bad it can't be made perfect. Oh well. :)
[center][/center]"The geek shall inherit the Earth."

Neil

PS you only need to put using namespace std;

Ashutosh32

In common usage I have seen ! being used as factorial.

BC_Programmer


Since we've got a bumpfest going on...



Public Function Factorial(ByRef Num as Double) as Double
    Factorial = Num * Factorial(Num-1)
End Function


VB6 doesn't let you do operator overloading though...


Quote from: Ashutosh32 on February 11, 2009, 10:17:19 AM
In common usage I have seen ! being used as factorial.

That's why Dilbert has defined the ! as an operator, Silly  ;D

the ! is one of a slim number of Postfix operators, where the operator appears after the number/value it operates on. NOT fun to try to parse an expression and handle these... Definitely a bigger pain then your standard  Unary operator (such as minus)
I was trying to dereference Null Pointers before it was cool.

diDy


Helpmeh

Quote from: diDy on March 15, 2010, 07:29:25 AM
What is an expression
This section of the forum is for answering questions that are frequently asked, just like yours. If you can't find your answer in this section of the forum, try this section: Computer Programming
Where's MagicSpeed?
Quote from: 'matt'
He's playing a game called IRL. Great graphics, *censored* gameplay.