Hard Light Productions Forums
Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Topic started by: Bobboau on April 27, 2005, 03:54:13 am
-
[edit]new build, handles negitive numbers and beter evaluation[/edit]
http://dynamic4.gamespy.com/~freespace/forums/attachment.php?s=&postid=666534
if you care at all about anything you will run this program and try to break it, you enter any normal mathematical expression (no trig or other type functions yet, just +-*/^) it will evaluate it corectly, if it fails to do so post here describeing what the conditions of failure were (post your expression) I am only going to get two hours of sleep because I stayed up all night working on this FOR YOU the least you could do is test the hell out of it for fifteen minutes. this is for the material and other systems (wouldn't you like user defined variables for the HUD?) it is a simple ugly looking thing but it is crucal that it works flawlessly
testitestittestittestittestitNOWWWW
instructions:
enter a simple (just arithmitic no log or trig (ect...) functions I do intend on implementing them eventualy but not just now) math formula, you may use any number includeing multi-diget and containing decimal points parenthises(ect...), it doesn't quite handle negitive numbers yet but it will.
hit enter
use a calculator to see if it was right.
tell me what happened, whatever the case.
if your not sure weather or not something is suported, try it! godamit!
I realy hope that when I wake up in 2 hours that there's like 40 posts here and not like... none, like there probly will be...
sleep.........
[edit]new build, handles negitive numbers and beter evaluation[/edit]
http://dynamic4.gamespy.com/~freespace/forums/attachment.php?s=&postid=666534
-
Awesome. :) I'll definitely test this tomorrow.
-
When I download it I get a PHP file.
Firefox doesn't read that.
-
(49*49-49)+((3+3)/3): Result 2448
(2401-49)+(6/3)
2352+2=2354.
(200/30+20): Result 6.66667
(200/30)+20)
6.6667 + 20 = 26.6667
10*10+20: Result 100
50/5+50/10: Result 10
Also, if you have any two operands together, or if you start an equation with an operand, it crashes the program. So entering:
+20 causes a crash as does entering 20+/10.
-
Tested it and it told me that
(1+2)*2+2 = 6
the last "2" isn't evaluated for some reason.
-
3/2*3/2 = 2.25
3*2/3 = 2
2*3/2 = 3
3*2*1 = 6
3+2+1 = 6
3*1*1 = 3
3/1/1 = 3
3+1/2 = 3.5
3-(3+1)/2 = 1
3-(3+1)/2+1 = 2
(2+1)*(2+2) = 12
(2+1)*(2+2)-1 = 12 Incorrect
((2+1)+3)*2 = 12
2^2 = 4
2+2^3 = 10
(2+1)^2 = 9
(2+2)^(3-1) = 16
(3+2)/(3-1) = 2.5
(2.5+0.5)*2 = 6
(2.5+.5)*2 = 6
Note the incorrect result above, pretty good basis for a numerical parser/evaluator. Hope you can work out the bugs.
-
0/5 = 0
Is this really correct?
I think there this shouldn't have any result...
You should get some kind of error if you try to divide 0 with 0.
Everything else I tried worked perfectly. ;)
-
Originally posted by DaBrain
0/5 = 0
Is this really correct?
I think there this shouldn't have any result...
Yes, that's correct, since it's equivalent to 0 * 1/5
You should get some kind of error if you try to divide 0 with 0.
Correct again, and Bob's program gives INF back, when you divide by 0.
-
Ah, right... Looks like I deserve the mark I got in math... ;)
-
You should get some kind of error if you try to divide 0 with 0.
Correct again, and Bob's program gives INF back, when you divide by 0. [/B]
0/0 = indefinite
I presume the prog calculates that properly.
-
huh... looks like it doesn't handle higherlevel opperations before lower level ones (ie if you * before you - without parenthises around the * block, it will perform the following subtraction incorectly)
-
Aren't there math libraries you could use?
-
huh... looks like it doesn't handle higherlevel opperations before lower level ones (ie if you * before you - without parenthises around the * block, it will perform the following subtraction incorectly)
that should be pretty easy to fix though, right? just throw in a loop checking for the higher levels first
oh, and i couldnt get the thing (firefox), else i'd have run it some too...lemme try with IE
-
ok, i looked a little deeper into one of the Incorrect problems above...
(2+1)*(2+2)-1 = 12 Incorrect
(2+1)-1 = 2 Correct
2*(2)-1 = 4 Incorrect
2*2-1 = 4 Incorrect
2*2-1+2 = 4 Incorrect
(2*2)-1 = 3 Correct
So...yeah, that's odd.
-
Originally posted by Inquisitor
Aren't there math libraries you could use?
I think this is a school project that involve trees IIRC back to the days of Data Structures.
-
2^2*2+2=4 MAJOR WRONG
Even if it fubars the operator priority, it should work left-to-right, correct? Then it should do:
2^2*2+2
4*2+2
8+2
10
Also, note in whatever documentation that it wants points, and not commas. (EU vs US rules, or Dutch vs English)
15+5*5=40, nice and correct. (Ergo, it does seem to do some kind of operator preference.)
5*5+15=25.
(5*5)+15=40. So it works well with brackets.
It also exits without error on any NAN entry.
2*4+7=8. Pretty wrong. It seems that if you do x*y+z you will always get something odd. Perhaps it gives you just x*y, and forgets z.
Yup, it does. x*y+z gives you x*y.
Also seems x/y-z gives you x/y.
z+x*y gives you a correct answer. (z+(x*y)).
z-x/y gives you z-(x/y), correct as well.
3^-5 gives an ugly crash. (Want the MS bugreport? Msn at [email protected] )
Seems to reproduce for x^-y.
Ditto for x^(-1*y).
However, x^(y-z), when z>y, works, and gives a correct answer.
BTW, can you make it so it'll take an expression as command line arg, and return the result? I could write a testing thing with random expressions in no time.
I'll test some more after dinner, but an argument thingy would be great.
EDIT: Got source? I might be able to read the C and find the bug, if you'd allow a total beginner to touch the code.....
-
Also, if I type 1.23456789 I get 1.23457. It seems to round after the 6th decimal, but it rounds correctly.
The only way to create a negative number is to do (1-2)*x, where x is your number.
9\3=9
9/3=3
I know I used the wrong slash, but it might be better to die more graciously.
It seems that if it does not recognise an operator, it returns the value of anything in front of the unknown operator, and ignores the rest. An error return/debug output should be in place to prevent the really odd bugs. (x+y=z gives x+y). It does check for odd stuff at the start of an expression, just not for odd stuff inside the expression.
The ! is not implemented yet.
In the final implentation, e, pi, and any other constants should be replaced by the apropriate value, something that shouldn't be forgotten.
Also, mashing a lot of keys and adding a few ^operators returns 1.#INF. Anything above 2^127 returns that, actually. Might be worth to add that to docs too. I geuss you're using signed floats, and anything out of bounds is called infinite?
(1-2)*2^127 works as expected.
-
Originally posted by Inquisitor
Aren't there math libraries you could use?
I don't think so. What Bobb's trying to implement (correct me if I'm wrong) is what I described for the HUD system, but never got working. The idea was to allow one-line equations to be used to control variables on the HUD. That wayyou could combine variables for a variety of gauges. Say if you wanted a HP gauge, you use the variable "self.hull_strength". If you want a HP % gauge, you use "self.hull_strength / self.total_hull_strength * 100". That way, coders only need to define a base set of variables and modders can combine them any way they please.
-
2^3/4 = 8
2^3/2 = 8
2^3/20 = 8
(2^3)/4 = 2
8*6+3 = 48
8*6+90 = 48
(8*6)+3 = 51
-
there is now a new build up, I will be trying all the expressions the last one failed, I'm fairly sure this is at the least better than the last build, it has a totaly reworked expression parser.
-
I would try, but then I'd actually have to do the math to test if the responses are correct. And I'm not that confident in my own maths skills. :p
-
it's called a calculator.
-
Works good now, I tried mine and a few other equations posted in this thread and all worked.
Doesn't seem to support negative numbers too well:
NOTE: Spacing is important and I tried to be exact, since it seems to break stuff.
-5 + 3
"3 = 3"
3 + -5
"-5 = -5"
3+-5
"3+-5 = 8"
(3)+(-5)
"(3)+(-5)" = -2
3 + 4
"4 = 4"
4 + 3
"3 = 3"
(3) + (4)
"(4) = 4"
3+4
"3+4 = 7"
The % operator also behaves oddly:
4%3+7
"4%3+7 = 0"
(4%3)+7
"(4%3)+7 = 4"
Edit: Sent the link to a friend.
3^-2
"3^-2 = 9"
3^(-2)
"3^(-2) = 0.111111"
-
I don't have modulus in yet, I'm suprized that worked at all.
I should have mentioned only inital rudimentery suport for negitive mumbers has been added, you'd be suprized how complicated it is to figure out weather a '-' means subtract or negate. right now it looks to see if the charicter on the other side of the - sign is a NULL or a ( indicateing that it's at the start of an expression, I guess it should also see if there are any opperateors there.
see if the general mechanisms for positive numbers works corectly while I work on getting this working
-
Originally posted by Bobboau
it's called a calculator.
Eh? Whassat?
-
magic
ok and now I have version 3 uploaded, I real realy think I got negitive numbers working now :)
wait a secon I just DLed it and it's weird
-
First impression (Ignore the cutoffedness, that'd be the stupid dos box):
3 + 4
3 = 3
if this is not corect, please tell me and provid
enter another expression or type exit to do so:
+ = 0
if this is not corect, please tell me and provid
enter another expression or type exit to do so:
4 = 4
if this is not corect, please tell me and provid
3+-5 still doesn't work properly...
3^-2 still doesn't work properly...
-
ok, new post new atachment
[note to self]don't modify atachments
use this atachment, it looks like when I changed the old exe it got corupted or something, a fresh upload should work good, I know for a fact those expressions are all working on my machine
-
Both of the bottom equations work now, although it keeps thinking that a space = a new equation.
*Tests some more*
Edit:
-(2^-(3)+1)-3 = 10
2^-(3) = 8
-(9)-3 = 6
3-(9)-3 = -9
-
"although it keeps thinking that a space = a new equation"
thats a..ehh..... undocumented feature! er..yeah that's it, not a bug...
but seriously, hmm, interesting, that must be doind that at a high level, higher than the classes I'm testing, because its giveing the whole output thing.
seems to indeed be a 'feature' of cin and/or string.
-
hmm hadn't thought of that, looks like I'm going to have to make a class of unary operators also.
-
ok, I need to sleep, if you want to play with this tonight, here is the full source for that console app. seems like I'm going to have to pre process the input infix data and find unary '-'s and give them some specal tolken. then add a whole new class of opperators that only have one operand, I was going to need to do this eventualy to suport sin, cos, (ect).
sleepy time :)
#include
#include
#include
#include
#include
using namespace std;
struct ship{
float a;
};
class variable{
public:
virtual float value(ship*shipp=NULL) = 0;
};
class constant:public variable{
float val;
public:
constant(float in):val(in){};
float value(ship*shipp=NULL){return val;};
};
class operate:public variable{
protected:
variable *operand1, *operand2;
public:
virtual float value(ship*shipp=NULL) = 0;
operate(variable*op1, variable*op2){operand1 = op1; operand2 = op2;}
~operate(){if(operand1)delete operand1; if(operand2)delete operand2;}
};
class add:public operate{
public:
add(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) + operand2->value(shipp);}
};
class sub:public operate{
public:
sub(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) - operand2->value(shipp);};
};
class divide:public operate{
public:
divide(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) / operand2->value(shipp);};
};
class power:public operate{
public:
power(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return(float)pow(operand1->value(shipp), operand2->value(shipp));};
};
class mult:public operate{
public:
mult(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) * operand2->value(shipp);};
};
class expression:public variable{
int n_var; //number of variables in the expression
variable *head; //the head of the expression
void postfix(string&);
variable* parse_next(char*&);
variable* get_ship_variable(char**);
public:
expression(char*);
~expression(){for(int i = 0;i float value(ship*shipp=NULL);
};
/*
variable* con = new constant(1.0f);
variable* op = new add(con,con);
*/
expression::expression(char* in_str):n_var(0),head(NULL){
string str = in_str;
postfix(str);
char* is = new char[str.length()+1];
char* os = is;
strcpy(is, str.c_str());
head = parse_next(is);
delete[]os;
}
variable* expression::parse_next(char*&in_str){
//kill any noise
while((*in_str == ' ' || *in_str == ' ') && *in_str != char(0))in_str++;
char ship_idnt[] = "ship:";
char op_char[] = "+-/*^";
if(!strcmp(in_str,ship_idnt)){
(*in_str)+=strlen(ship_idnt);
//it's a ship variable
return get_ship_variable(&in_str);
}else{
//it's a constant, or an opporateor
if(strchr(op_char, *in_str) && *(in_str+1) == ','){
//it must be an operator
char o = *in_str++;
if(*in_str == ',')in_str++;
variable*a = parse_next(in_str);
variable*b = parse_next(in_str);
switch(o){
case '+':return new add(a,b);
case '-':return new sub(a,b);
case '*':return new mult(a,b);
case '/':return new divide(a,b);
case '^':return new power(a,b);
}
}else{
//it must be a constant
char *str = in_str;
while(*(in_str) != ',' && *in_str != 0)in_str++;
if(*in_str == ',')in_str++;
return new constant(atof(str));
}
}
return NULL;
}
variable* expression::get_ship_variable(char**){
return new constant(0.0f);
}
inline int get_value(char c){
switch(c){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:return -1;
}
}
bool is_value(char c){
if(c >= '0' && c <= '9')return true;
if(c == '.')return true;
return false;
}
void fix_implied_mult(string &str){
for(int i = 1; i< str.length(); i++){
if(str[i] == '('){
if(!get_value(str[i-1]))
str.insert(i,"*");
}
}
}
void reverse(string&s){
string out = "";
int l = s.length();
string temp = "";
for(int i = 0; i for(i; i temp += s[i];
if(!is_value(s[i]) || !is_value(s[i+1]))break;
}
out.insert(0,temp);
temp = "";
}
s = out;
}
void expression::postfix(string& str){
string s = str;
fix_implied_mult(s);
stack op_stack;
string out;
reverse(s);
int i = 0;
while(s[i]){
if(is_value(s[i])){
int sidx = i;
while(is_value(s[i]))out+=s[i++];
if(s[i] == '-' && (s[i+1] == 0 || s[i+1] == '(' || get_value(s[i+1]) != -1)){
out+="-";
i++;
}
out+=',';
}else if(s[i] == ')'){
op_stack.push(s[i++]);
}else if(s[i] == '('){
while(op_stack.top() != ')'){
out+=op_stack.top();
op_stack.pop();
out+=',';
}
op_stack.pop();
i++;
}else{
int v = get_value(s[i]);
if(v){
//it's an opperator
if(op_stack.empty() || op_stack.top() == ')' || get_value(op_stack.top()) <= v){
op_stack.push(s[i++]);
}else{
while(!op_stack.empty() && get_value(op_stack.top()) > v){
out+=op_stack.top();
op_stack.pop();
out+=',';
}
op_stack.push(s[i++]);
}
}
}
}
while(!op_stack.empty()){out+=op_stack.top(); op_stack.pop(); out+=',';}
out.resize(out.length()-1);
reverse(out);
str = out;
}
float expression::value(ship*shipp){
return head->value(shipp);
}
void main(){
string str = "";
// string str = "(1+2)*(3+4)*(5+6)";
// string str = "1+(2+3*4^(5-3)-7)*3";
// string str = "1+2+3*4^5-6-7*8";
// string str = "1+2*3+4";
// string str = "1*(2+3)";
// string str = "2*3/(2-1)+5*(4-1)";
// string str = "49*49-49";
cout << "enter an expression or type exit to do so\n";
cin >> str;
while(str!="exit"){
char test[512];
strcpy(test, str.c_str());
expression exp(test);
// cout << pow(4.0f,5.0f);
cout << "\n" << str << " = " << exp.value() << "\nif this is not corect, please tell me and provide the expression you entered\n\nenter another expression or type exit to do so:\n";
str = "";
cin >> str;
}
cout << "thank you for testing me";
}
-
it is actually a "feature" of cin. cin leaves whatever comes after whitespace in the input stream without removing it. use cin.getline() instead if you want to avoid that particular feature.
-
This is one reason why I never use cin, cout, or filestreams. :p
-
1-2*2 = -3
wrong
-
Actually Drew that's right. 1-4 is -3.
-
Multiplication comes before subtraction in orders of operation, Drew.
-
Bobb: What about doing what the TI calculators do and use a different minus sign for the negative and the substraction? Use an underscore or something for one of them.
-
Originally posted by StratComm
Actually Drew that's right. 1-4 is -3.
not when you work the operations seperate. whatever.
-
WMC, I hope you don't mind me using your example :p.
-(2^-(3)+1)-3=10 FALSE
-1*(2^(-3)+1)-3=4.125 TRUE
It's all in the way you write the equation. In basic, low level mathematics, the first statement is invalid. Understood elements cannot be parsed, because the program doesn't know what understood element it is. Therefore, direct logical equations must be used.
EDIT: If I may ask, why are we playing with this calculator? What is it for?
-
Originally posted by kasperl
Bobb: What about doing what the TI calculators do and use a different minus sign for the negative and the substraction? Use an underscore or something for one of them.
It'd be a real pain to do that since you'd have to open up charmap every time you wanted to use a negative.
Although I suppose tilde or something could be subbed in...it'd make the code less readable though.
-
I know it isn't fun for readability, but it'd save a ****load of coding, and quite a few ambiguities.
-
or do something like using tilde or another character as your "negative" minus sign rather than subtraction operation.
-
screw readability, once you get it working once, don't touch it again :p
-
I think I'm going to have any time it finds a '-' without an operand on either side it'll replace it with '-1*', sence -# is working
-
what about (a)-(b)?
-
this change fixes it I think.
it actualy replaces any '-' that does not have a valid charicter before it with '(-1*' and finds the end of the block it's being multiplyed with and adds a ')'
so -x is replaced with (-1*x)
-(14*5+3) is replaced with (-1*(14*5+3))
void fix_implied_mult(string &str){
for(int i = 0; i< str.length(); i++){
if(i && str[i] == '('){
if(!get_value(str[i-1]))
str.insert(i,"*");
}
if(str[i] == '-'){
if((!i || (!is_value(str[i-1]) && str[i-1] != ')') )){
str.insert(i,"(");
int p = 0;
for(int k = i+2; get_value(str[k]) == -1 || p; k++){
if(str[k] == '(')p++;
if(str[k] == ')')p--;
}
str.insert(k,")");
str.insert(i+2,"1*");
i+=3;
}
}
}
}
-
test build!
-
enter an expression or type exit to do so
-(9+11)
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
-
void fix_implied_mult(string &str){
for(int i = 0; i< str.length(); i++){
if(i && str[i] == '('){
if(!get_value(str[i-1]))
str.insert(i,"*");
}
if(str[i] == '-'){
if((!i || (!is_value(str[i-1]) && str[i-1] != ')') )){
str.insert(i,"(");
int p = 0;
for(int k = i+2; (get_value(str[k]) == -1 || p) && str[k]; k++){
if(str[k] == '(')p++;
if(str[k] == ')')p--;
}
str.insert(k,")");
str.insert(i+2,"1*");
i+=3;
}
}
}
}
ok, try again
-
if i put in -1 by itself, the thing crashes
-
-x by itself crashes in general
-
enter an expression or type exit to do so
-(9+11)
-(9+11) = -20
if this is not corect, please tell me and provide the expression you entered
enter another expression or type exit to do so:
2^-(1)
2^-(1) = 0.5
if this is not corect, please tell me and provide the expression you entered
I think you got that part down, bob :).
-
-((2/4)*3+(2^2)+6)-3 = -14.5
This seems wrong....
= -((0.5)*3+(4)+6)-3
= -(1.5)+(10)-3
= -8.5
Though my maths brain cells haven't been used in years, so it could be down to my knowledge of BODMAS ;) It was the only calculation that seemed a bit off.
EDIT : This was prefix 5, I'll try 6 now :) Still -14.5. Someone check my maths, I'm still not certain ;)
-
someone pointed out something screwed up, new version better implyed multiplication suport now.
-
Sorry flip, your math is wrong :p. You got the first line right, but you will notice how you made your mistake.
= -((0.5*3)+4+6)-3
= -((1.5)+10)-3
= -(11.5)-3
= -14.5
There was your problem. As my old math teacher said, "the most important part of an equation is the attention to detail".
-
Ahhh... yes, the -3 is outside the brackets and so applies after the equation has been inversed :) I'd need another set of brackets to get the result I got ;)
Ah well, told ya it'd been a while ;)
-
because I'm on a computer were I can't save, I'm uploading my code
-
Compiled version (EXE):
-
I'm going to assume that the silence means no one has found any more errors...
-
I tried for an hour to try and break this thing, and it isn't letting me fail, so long as I follow standard mathematical procedure. However, it seems to think that 0.999_=1 :p.
Suggestions, error handling like ending parenthesis should be present. Also, how about a root function? Cubic root of 27 could be written as 3r27, and it would ofcourse resolve to 3.
-
x=x = 0 seems kinda strange but i guess = isnt an treated as an operater
-
this isn't an algebraic symbol simplifier, it's an arithmitic evaluator, no '='
-
yay!
sin sqrt tan log cos ln!!!
also x#y = the x'th root of y
oh, yeah, modulus (%) is working now.
-
ok,
1)does everything work
2)what else do I need to add
-
1)I don't know the order of the operations for trig/calc (nor do I know trig/calc period :p), so I can't tell you.
2)That all depends on what it's used for. You still haven't told us, yet.
-
well I'm developing this for the materia system, but it'll probly end up getting used in a new HUD system and linked animations.
come on now folks were in the home streach, don't quit on me now...
-
Rad/degree?
I do see it is in radians.
You still need to implement ! (3!=1*2*3).
Do we have arctan, arcsin, and arccos?
It doesn't seem to support unreal answers, btw.
We either need constants like pi available, or some kind of accuracy control:
sin(3.1415926) = 1.50996e-007'
(My TI says sin(pi)=0, like it's supposed to.
It does work when not aproaching zero:
cos(3.1415926) = -1.
tan((1/8)3.1415926) = 0.125655
TI:
tan((1/8)pi)=.414213
Perhaps it doesn't multiply when no char found.
Indeed it doesn't....
tan((1/8)*3.1415926) = 0.414214
It totally dies when you fo
rget to close your bracket.
It still doesn't trow out an error if it doesn't support the operand.
(arcsin(1)=0)
EDIT:
Log and ln work as expected, ditto for #.
We definately need constants though, stuff with e in it just gets odd.)
-
try PI and E
"sin(3.1415926) = 1.50996e-007'" that is what's known as a rounding error, that's as close to right as a computer ever gets.
I need to fix implied multiplication for the closeing side of parenthises aparently.
and also added to the todo list, better parenthises error handleing, it shouldn't be too hard to append the corect number of parenthises to the end of an expression, or at the very least handle it without crashing.
will add arc* and hyperbolic trig functions when I get home tonight. any other unary {y=f(x)} functions anyone wants?
I supose a degree(radian_number) and radian(degree_number) should be added.
and I'll add factorial.
and I'm not going to suport imaginary numbers.
-
Erm...are arcsin(), arccos(), etc. in ?
-
not yet, and if you try to use them it will quite likely crash, at the very least it'll give bizar output if anything.
as I said, I will get them in tonight, it'll be a trivial matter to add these.
-
just thought of something to add, log of a variable base. how's this sound X~B gives you the log(base B) of X
-
Well, log(x)/log(b) works fine....
And any operator or function it doesn't recognise will return zero, it seems. It really should return an error, IMHO.
I'm simply looking at the catalog of functions on my TI and putting anything of which I know what it does and isn't in yet.
abs(x)
(wtf is cosh?)
Degree/Rad conversion
Dec-->Frac might be handy, but I doubt it'll work...
int( ). (I think it'll give the rounded int value of anything it gets)
rand might be a good thing somehow....
That was the TI catalog, anyway, dunno about anything else.
Do you want probability calculations?
-
cosh is hyperbolic cosine, I'll be adding all three hyperbolic functions.
the thing with log is, the fewer variables (opperators are counted as variables) used the better, so if I can make an opperator that can do something common with being passed two variables (1 opp + 2 param = 3 variables) rather than useing 6 it'll be twice as fast, the evaluation uses recersive calls to many derived claasses so it is inherently slow as it is.
ipart and fpart would probly come in usefull
abs() definately!
there realy isn't any way to use fractions like that, evaluateing an expression is built from the ground up to return only a floating point value, not another expression. although makeing a function to take a float and display a fraction might be nice to have around in general.
rand() would defenately be useful (I can think of a material for flickering debris would use it right away), two implementations a 'rand' wich returns a number between 0.0 and 1.0 and a range version, I'm thinking 'A?B', returns a value between A and B, though I might want to reserve '?' for posable conditionals later on.
-
ok so the complete list of functions that are not currently suported but will be a short time after I get home tonight are(is? :wtf:.. anyway):
arcsin(x)
arccos(x)
arctan(x)
hypsin(x)
hypcos(x)
hyptan(x)
degree(x)
radian(x)
!(x)
abs(x)
ipart(x)
fpart(x)
sign(x)
rand {and a binary verion for range, needs to be one charicter long}
~ {log of variable base}
-
Originally posted by Bobboau
not yet, and if you try to use them it will quite likely crash, at the very least it'll give bizar output if anything.
as I said, I will get them in tonight, it'll be a trivial matter to add these.
Ah...I overread that. It doesn't crash though, just returns 0.
For other functions:
- Complex numbers (if there's any use for them)
- sign(x) is handy sometimes
-
sign?
Complex numbers, I reallly can't see any use for those in materials or the HUD....
Same thing with Probability calculation, I geuss.
Some way to do formulas and derivations might be needed somewhere in the HUD thing if you want stuff with distance/speed/accel, but you couldn't do it properly since you don't have a proper formula for anything. I think just doing (f(x)+f(x+h))/h is the only really probably way of working that in. You might want a function for that, if it really saves time. I can see functions like that being used in the HUD a LOT.
BTW, is there any limit on the number of brackets one can use?
-
sign(x) =
= 1 for x > 0
= 0 for x = 0
= -1 for x < 0
-
added.
I realy don't think that there is any way to do derivitives/integrals properly, there is no way of getting what the value of something was last frame (though frame time should be available) anything that you'd want the information for it will probly have a hard coded ship variable for it anyway. so I don't think I'm even going to contemplate any calc opperations, so no df/dx.
there is no limit on the size or complexity of the function (in theory) and you should be able to use as many parenthises as you want (so long as you make sure you close them all)
-
'nother question: Any way at all to do something a bit more permanent then a single frame? It'd be a good thing for the HUD, obviously, and also when you need to do flickering materials you need to record a certain length of time, I would think.
Since framerates can vary greatly, and you don't want to cause a migraine/epiliptic attack for those with a good rig, while those on a slower computer see the flickering once a second. (Gross exeguration, but you get the idea.)
Would SEXP variables be accesable by this part of the code? (I'm thinking HUD here again.)
-
Like SEXP evaluation or beam damage, this should only be done in fixed intervals. That's pretty obvious, as you want the effect to be framerate dependent.
-
for flickreing you don't need to know anything, you just need to make a simple probablistic formula sign(ipart(rand*(1.0/probability))) will give an out put of 1.0 at the specified probability., it would be constant flickering, so you would do something like sign(ipart(rand*(1.0/(probability*sin(time/10)*sin(time /11)))))
sExp values can be rereived, as well as any global.
-
Bobb, can you (please) make this OO? I have nothing against a probability variable, but something like "math.probability" would make things clearer, and easier to document.
If that seems too long, we could follow with a shorthand system that would allow "m.p", by basically aliasing the command names. sexps could be
sexp."variable name" or sx."variable name"
with ships
ships."ship".variable or s."ship".variable
I think the OO/shorthand system would let us add mass amounts of variables without running out of names (as often) or having things get disorganized. Whether or not it's true OO or just a string with a dot in it won't matter in the shortterm.
Kasperl: The way that things are handled, if you want to have something flicker half a second, it'll work. FS2 basically increments the mission timer by frametime. If you wanted something to flicker once every two seconds:
$Brightness: 255*(mission.time%2)
Freespace would increment the mission.time properly to account for any frame lag, then /2, find the result was either an odd or even number. On an even second, the gauge/texture would be off. On an odd second, the gauge would be on.
-
when I said probability in that statement I meant what ever the probability of the light being on was, like if you wanted it to be on half the time then you would put 0.5 in.
-
Originally posted by redmenace
I think this is a school project that involve trees IIRC back to the days of Data Structures.
Hey, that's exactly what I'm learning right now. Abstract data types and stuff - stacks, queues, binary search trees, 2-3 and 2-3-4 trees, heaps... it's fun. :D
-
Originally posted by Bobboau
when I said probability in that statement I meant what ever the probability of the light being on was, like if you wanted it to be on half the time then you would put 0.5 in.
Ohh, alright.
-
though if there is going to be a lot of demand it might be a good idea to make a flicker(x) function, just a thought.
ok, new build I'm prety sure this just about sums everything up, the only thing it lacks is a rand function, because I'm going to use the one in FS already so I need to wait untill I reintegrate, and I've decided on how I'm going to implement it, it will be passed a variable, it will return a number between 0 and the number passed, this will make it simple to implement and generaly flexable.
I haven't done this yet, but it won't matter because it's currently just a stub feature anyway, rather than being passed a ship pointer, I'm going to have it pass an object pointer, and the evaluating functions for each of the ship variables will be able to handle weapons and shock waves and fireballs and any other object type the only place were it won't get a pointer is in the tech room, and in the sky box code.
-
ok, once again, I can only assume that the 12 hours of deffoning silence implies that everything is working perfictly, and it's almost tme for me to reintegrate it into the game so I hope there aren't any bugs left.
-
I couldn't find anything while testing, no. That doesn't mean it's infallible. Especially in the outer bits of the float range the thing will behave oddly.
-
ok, I've worked out the object variable syntax, it's sort of an odd OO style setup, but toaly diferent than any exsisting language (because I already have the '.' defined as part of a number)
all game variables will start off with the ':' charicter, then there will be which groupe of variables you want, currently all I have defined is object (meaning the currently rendered object) but I will likely also have :global, and maybe :player_object and :targeted_object (though this could probly be done via :object{targeted object{whatever}}). after this is a set of {}s with the name of the variable in it so to get the currently rendered object's engine output, you'd type
:object{engine_output}, currently this is being tested with a bunch of stubb data, so it realy isn't anything to test, just look to see if there are any further glareing errors in the last build.
-
Hmm, I dislike that way for a few reasons.
1):object doesn't seam as intuitive as object:
2):object{member objectvar} seems similar enough to functions to be confusing when reading code, and you have to keep track of the number of closing braces...unlike parentheses, they aren't really denoting a section per-se.
3)both the : and the {} characters all require you to hold down shift, which is a little annoying (for me anyway)
4)No other coding language has used that system, as far as I know, unless it's from some shader language...meaning you have to learn + get used to an all new syntax. If we ever implement a full scripting system, it'd add needless confusion as well
Wouldn't it be possible for the parser to do something like this? (this is pseudo-code, as I didn't fully understand how the parser actually parsed the various operators and have to be somewhere in 10 min)
if(isletter(currentchar))
{
while(isletter(currentchar))
{
currentchar++;
}
if(currentchar=='(')
return THIS_IS_A_FUNCTION;
else if(currentchar=='.')
{
return THIS_IS_AN_OBJECT_ITEM;
//Next function does this
if(currentobject)
add_object_child(currentparseitem);
}
else
{
parse_error("Somebody used an invalid thingamabob!");
}
}
Unless you've got another reason for using the :{} syntax or that'd be really hard to do with the current parser
I still need to test the last build.
Edit: SYNTAX ERROR :p
-
Disabling smilies might be a good idea BTW....
-
yeah
and the reason I have a thing to start and end members is because the string gets read backwards so I need something to denote the end of a member as well as the begining of a game variable, when the string is getting converted to postfix notation it is reversed, ans what if by sone twist of fate the end of a mamber variable hapens to end in "log" or "sin" or something that I already have a check for, it's just simpler to go if you fiind '}' copy everything untill you find ':'. '}' isn't currently used by anything so the only posability is that we have a member of an object.
I doubt anyone useing this is going to be a coder, so it doesn't matter if it looks like function syntax.
I supose I could change it to :object.member: everything between two colens gets coppied as a single operand. but I've already started integrateing it into the game again, so I'll just have to wait untill I get the game working with it again, it should be a simple change.
-
Yeah, I sort of like that better.
Couldn't you check if 'log' actually is the end of a word or a variable? Since all variables would have '.' in 'em, any contiguous string with a '.' should automatically be processed as a variable.
I can try and do that once you've got it into CVS.
-
20*.3 = 6
??? Since when.
And since when does 9999*.3 = 2999.7
-
ummm... sence decimal numbers were invented I supose, so... I don't know... 2500 B.C. maybe?
those are corect. at least acording to my $150 calculator, and MScalculator, and google... am I missing something?
-
Originally posted by MatthewPapa
20*.3 = 6
??? Since when.
And since when does 9999*.3 = 2999.7
You're thinking division.
.3, 20 times, is 6 ;)
-
.3 is 3/10.
-
well it's good that my code is starting to out think some peaople... probly...
-
We don't know that... Yet :p.
-
Originally posted by Raa
You're thinking division.
.3, 20 times, is 6 ;)
Thats what im saying. I was just wondering if that might be a problem.....whatever.