#basic calculator

1 messages · Page 1 of 1 (latest)

stark hinge
pastel skiff
#

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

stark hinge
#

i did but then i combined lexing, parsing, and interpreting all into one step

pastel skiff
#

You’re doing way too much with lambdas here

stark hinge
#

i still have an older version with those separated so i might improve on that

pastel skiff
#

Lol

real hull
#

One question: is this calculator for expressions in RPN or infix-notation?

stark hinge
#

what do those mean?

pastel skiff
#

You’ve already earned your spaghetti master title in satisfactory, no need to prove it in C++ too we get the point 😛

real hull
#

like 5 3 + vs. 5 + 3

stark hinge
#

the latter

real hull
#

even better 👍

stark hinge
#

normal math expressions

frosty mist
#

i cant laugh too much, my rpn calc was spaghetti too

pastel skiff
#

(As far as spaghetti goes, though, this is fairly nice spaghetti. Just too much lambda nonsense)

stark hinge
frosty mist
#

just a different type of function no?

stark hinge
#

no i actually don't notice any difference in compilation time

frosty mist
#

a

stark hinge
#

but i imagine it has accumulated over the years

#

the nanoseconds add up

pastel skiff
#

Lambdas shouldn’t be too expensive

#

You can benchmark though

frosty mist
#

lemme check if my rpn calc is public

stark hinge
frosty mist
#

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

stark hinge
#

better organized than mine

#

oh i am quite proud of my error detection though

frosty mist
#

yeah mines bare

#

i need to come back to that project

#

yours is very concise though, cant really read it on mobile

real hull
#

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.

real hull
#

could have added support, but it was originally a throwaway experiment

frosty mist
#

ah

stark hinge
#

which i could have probably easily done with recursion

real hull
# frosty mist ah

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

stark hinge
pastel skiff
mystic pagoda
#

also I think it could be simplified with find_first_not_of

mystic sail
#

wtf when did ecz write real code

#

this is cursed go back to weird magic

stark hinge
meager coral
#

🧀 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 kekw

foggy mauve
#

@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();}
stark hinge
#

?

foggy mauve
#

That wouldn't compile

#

Compilers extensions ftw

stark hinge
#

why wouldn't it

#

where do you modify *i

foggy mauve
#

Try it

stark hinge
#

;compile ```cpp
const char* i = "abcdef";
++i;
std::puts(i);

hazy glenBOT
#
Program Output
bcdef
foggy mauve
#

strtof(i,&i)

stark hinge
#

ah

#

okay

#

well what i'm working on doesn't rely on extensions

vernal spindle
#

Eczbek your glorious work has inspired me to also write a calculator.

mental tusk
#

what's going on here

stark hinge
#

it's only used once

lunar crater
outer canyon
outer canyon
outer canyon
stark hinge
#

your calculator only supports single operations?

outer canyon
#

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"

stark hinge
outer canyon
lunar crater
#

it's pretty simple

#

give me a sec

#

this is what i used for my first compiler

outer canyon
#

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 😭

stark hinge
#

haha

nimble belfry
#

good to see u writing code tho

stark hinge
#

implying that xieite isn't code

#

lol

nimble belfry
#

its technically code

agile spade
#

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

stark hinge
#

you use it with stdin

agile spade
#

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?

stark hinge
#

you pass it a string and it returns a value (or throws)

agile spade
#

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.

stark hinge
#

ha

#

of course, it should be split into multiple parts

#

lexer, parser, interpreter

agile spade
#

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?

stark hinge
#

what's wrong with the loops?

#

oh and the purpose of this was education

agile spade
# stark hinge what's wrong with the loops?

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.

stark hinge
agile spade
#

You know the code better, just throwing stuff at the wall

stark hinge
agile spade
#

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...)

stark hinge
agile spade
stark hinge
#

i do, in one step

agile spade
#

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

stark hinge
#

i see your point, but it isn't that easy

agile spade
#

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?

stark hinge
#

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

foggy mauve
#

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
}
agile spade
#

So just for fun @stark hinge did you ask Copilot for a code review?

stark hinge
agile spade
# stark hinge 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.`

stark hinge
#

it already checks for valid input

#

checking for division by zero is an idea, i suppose

agile spade
#

The machines are sometimes better to kick than to read the output from ... and sometimes actually do spot something worth thinking about.

stark hinge
#
  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

mystic sail
#

but thats about it

stark hinge
nimble belfry
#

xieite in production 😨

stark hinge
mystic sail