#basic calculator
1 messages · Page 1 of 1 (latest)
Wow I’ve never seen you write actual code before
Nice code 😛
Definitely split up the logic here. Make some functions, split out some parts
i did but then i combined lexing, parsing, and interpreting all into one step
You’re doing way too much with lambdas here
i still have an older version with those separated so i might improve on that
Lol
One question: is this calculator for expressions in RPN or infix-notation?
what do those mean?
You’ve already earned your spaghetti master title in satisfactory, no need to prove it in C++ too we get the point 😛
like 5 3 + vs. 5 + 3
the latter
even better 👍
normal math expressions
i cant laugh too much, my rpn calc was spaghetti too
(As far as spaghetti goes, though, this is fairly nice spaghetti. Just too much lambda nonsense)
i paid for the lambdas (in compilation time), i will use all the lambdas i can
are lambdas really that expensive?
just a different type of function no?
no i actually don't notice any difference in compilation time
a
lemme check if my rpn calc is public
first i'll go back to the version with everything separated and improve that
ah idk how to check on mobile
this is what id done for mine
its uh
not pretty and has no syntax error detection
but it works pretty reliably
yeah mines bare
i need to come back to that project
yours is very concise though, cant really read it on mobile
There was one time I made a compile time RPN calculator (granted, no division though)
and left it somewhere in the depths of my gists. I remember showing the godbolt demo somewhere.
why no division?
could have added support, but it was originally a throwaway experiment
ah
oh also check out this code
https://github.com/Eczbek/cpp-calculator/blob/055299baef5b45da3e473c1159c1d7ff18e14719/main.cpp
it only doesn't support parentheses
which i could have probably easily done with recursion
The CE link still works (see asm output line 113 and try searching for the operator()() as well). Here you go, feel free to toy around with it. 🙂
https://godbolt.org/z/a5jdTqrsK
// maybe a constexpr RPN evaluator??
static constexpr auto temp_limit = 10;
static constexpr std::string_view source = "6 4 9 * +";
template <std::size_t StackLimit>
class CompEval {
private:
constexpr auto isSpace(char c) {
return c == ' ' or c == '\t' or c == '\n';
};
constexpr auto isDigit(char c) {
retur...
btw it completely breaks vscode highlighting
ah thanks
Nice lol
how about including \r, \v, and \f in whitespace
also I think it could be simplified with find_first_not_of
i thought about it then, but i guess i might as well include those now
🧀 Eczbek calculator 🧀
🧀 Eczbek calculator 🧀
Also call me pedantic but imo the main is doing way to much. A lot of this could be put into its own calculator class or something.
Also I agree with Zelis in you are using way to many lambdas
Also your lack of comments is disturbing young Jedi
Also I find it very whimsical how you manage to make even a simple calculator look complicated 
@stark hinge here fixed your code
char* i = (char*)"((2-3+2*(3-6)-1)/2.5)*(5+3^2)";using F=float;F z();F y(F a=z()){return*i==94?i++,y(pow(a,z())):a;}F x(F a=y()){return*i-47&&*i-42?a:x(*i++-47?a*y():a/y());}F w(F a=x()){return*i-45&&*i-43?a:w(a+x());}F z(){F r;return*i==40?i++,r=w(),i++,r:strtof(i,&i);}int main(){std::cout<<w();}
- char* i = (char*)"((2-3+2*(3-6)-1)/2.5)*(5+3^2)";
+ const char*i="((2-3+2*(3-6)-1)/2.5)*(5+3^2)";
?
No
That wouldn't compile
Compilers extensions ftw
Try it
;compile ```cpp
const char* i = "abcdef";
++i;
std::puts(i);
bcdef
strtof(i,&i)
Eczbek your glorious work has inspired me to also write a calculator.
splendid
hey so why is everything in a lambda
what's going on here
why wouldn't it be
it's only used once
too little indentation
This is mine
https://github.com/Iammethatisnotyou/calc
I agree
The groff page what?
your calculator only supports single operations?
No it can do more complex things like
LiamUSR@Liam ~/programs/c-cpp/compression > calc
-> 5 * 2 + 3 - 2
11.0000
Also your github doesn't include these two files
#include "../xieite/include/xieite/io/read.hpp"
#include "../xieite/include/xieite/math/parse_number.hpp"
oh yeah those are from https://github.com/Eczbek/xieite
ah, does it just do each operation in order?
No it doesn't do pemdas so thats why I put it in that order.
cool
add precedence
it's pretty simple
give me a sec
this is what i used for my first compiler
i see
I think I'll check out your calculator it seems cool. The calculator is heavy C++ code compared to my usual C but it's nice.
@nimble belfry
this is a... very interesting way to do it 😭
haha
good to see u writing code tho
its technically code
what are you trying to do with this monster? it's all lambdas in main with no usage string, no tests.
assuming it works, it's ... an interesting golf exercise
it isn't even golfed
you use it with stdin
Riding almost everything as lambda's in main counts as golf to me, because you wind up with a fairly impractical technical product.
How would you reuse this? Would you move it into new functions? Would you put all the lambdas in a linkable object that does not contain a main? Would you OOD it?
if there's no main function then the lambda can be a standalone function
you pass it a string and it returns a value (or throws)
Okay.
So, it... Is fairly dense code that is not something I really want to tear into if I don't have to. It looks like a ringer for a CLI tool in a Unix distro. Or an undergraduate project.
What version of C++ is this targeting? I am personally increasingly prejudiced against for loops that iterate or that use and index.
It is a strange- looking- to- me mishmash of advanced idioms and generic looking loops.
(I have a 20 lb baby on my left arm and my handy in my right hand, dictating messages, I am not currently able to properly edit text messages.)
I think the biggest thing that has gone unanswered, is why did you make this in the first place? Education? Exercise a arg parse library?
this requires at least C++23 because i use the explicit this parameter
what's wrong with the loops?
i do like this funky bit though
https://github.com/Eczbek/cpp-calculator/blob/main/main.cpp#L93-L111
oh and the purpose of this was education
If you're using 23, my personal preference is to ditch loops in favor of rangers and views as able. The stream/sequence processing feels like the better way to go, partly because it simplifies your scope for each iteration period C++ is also able to trivially parallelize some batch operations.
i can't use range loops because i increment a single variable, pos, between multiple different loops
Can't use an enumerate loop?
Or a stride 2 in other places?
You know the code better, just throwing stuff at the wall
pos is incremented all over the place
That's honestly somewhat alarming.
I mean, congrats on writing a whole basic calculator as a set of lambdas in the parameter of a println("{}", ...) (which is also C++23 addition...)
how else would you parse a string
it can work with std::cout
split into tokens, handle tokens.
i do, in one step
ex:
return string_view{s}
| views::split(" "sv)
| views::filter([](auto seq){return isalnum(seq.front());})
| ranges::to<vector>()
| views::reverse
| views::join_with(" "sv)
| ranges::to<std::string>();
You can also use a regex, though you'd need a lot of escape characters for a math expression parser
i see your point, but it isn't that easy
Yeah, since you have optional whitespace between the alternating numbers and operators, plus optional paranthetical additions to push onto a stack.
You said "the purpose of this was education" -- what did you learn? What worked, what didn't?
well i previously followed this book on building an interpreter
but it was written in java
it's been some time since then
so i took what i remembered and wrote it in c++
now i can expand on it
ok fine, here's my other version
#include "larley/string-grammar.hpp"
using namespace larley;
int main()
{
enum NonTerminals { Sum, Product, Factor};
using PT = ParserTypes<NonTerminals, StringGrammar::TerminalSymbol>;
using GB = StringGrammarBuilder<PT>;
using Range = GB::Range;
using Choice = GB::Choice;
GB gb{Sum};
gb(Sum) >> Product;
gb(Sum) >> Sum & "+" & Product | [](auto& vals) { return vals[0].as<float>() + vals[2].as<float>(); };
gb(Sum) >> Sum & "-" & Product | [](auto& vals) { return vals[0].as<float>() - vals[2].as<float>(); };
gb(Product) >> Factor;
gb(Product) >> Product & "*" & Factor | [](auto& vals) { return vals[0].as<float>() * vals[2].as<float>(); };
gb(Product) >> Product & "/" & Factor | [](auto& vals) { return vals[0].as<float>() / vals[2].as<float>(); };
gb(Factor) >> "(" & Sum & ")" | [](auto& vals) { return vals[1]; };
gb(Factor) >> Range{"0", "9"} | [](auto& vals) -> float { return vals[0].src[0] - '0'; };
auto parser = gb.makeParser();
std::string str = "(1+2)/3*4";
std::cout << parser.parse(str).as<float>() << std::endl; // outputs 4
}
that's pretty cool
So just for fun @stark hinge did you ask Copilot for a code review?
nah i don't care about LLMs
I find it interesting. Here's the skinny:
`🛠️ Suggested Enhancements
Implement Input Validation: Use loops and checks to ensure that the user inputs valid numbers and operators.
Handle Division by Zero: Before performing division, check if the denominator is zero and handle accordingly.
Refactor Operator Handling: Replace multiple if statements with a switch statement or a map of operator functions for better scalability.
Modularize Code: Create separate functions for each arithmetic operation to promote code reuse and clarity.
Enhance User Prompts: Provide detailed instructions and feedback to guide the user through the process.`
it already checks for valid input
checking for division by zero is an idea, i suppose
I'm not quite sure how you'd handle the look-ahead for a zero (especially if it'd be something like (8/2 - 4) but it's a keen idea.
The machines are sometimes better to kick than to read the output from ... and sometimes actually do spot something worth thinking about.
if (tokens[i].type == types::star) {
left *= tokens[i + 1].value;
} else if (tokens[i].type == types::slash) {
+ if (xieite::almost_equal(tokens[i + 1].value, 0.0)) {
+ throw /* something */;
+ }
left /= tokens[i + 1].value;
} else {
break;
}
probably
:(
xieite in production 😨
muhahaha >:)

