0

This code should divide a screen in a certain number of parts, and then compute the size of various drawings knowing how much "parts" each drawing needs.

#include <iostream>
using namespace std;

// number of divisions per element
#define AREA_MarginSX   1
#define AREA_SpaceSX    1
#define AREA_Drawing    4
#define AREA_SpaceCN    1
#define AREA_Chart      4
#define AREA_SpaceDX    1

#define AREA_Total_DIV  AREA_MarginSX + AREA_SpaceSX + AREA_Drawing + AREA_SpaceCN + AREA_Chart + AREA_SpaceDX

// L'area ORIZZONTALE totale viene divisa in questo modo:
// margine sx (etichette asse y), Aree x NumSensori, margine dx
#define DRAW_Margin_SX 3
#define DRAW_Margin_DX 1

// l'area verticale viene divisa in Margine inferiore, area del grafico, e margine superiore
#define DRAW_Margin_Bottom 2
#define DRAW_AreaHeight 13
#define DRAW_Margin_Top 1


int main() {
    int NumAreas = 3;
    int ScreenWidth = 480;
    int ScreenHeight = 270;

    int NumDivsX = DRAW_Margin_SX + AREA_Total_DIV*NumAreas + DRAW_Margin_DX;
    int NumDivsY = DRAW_Margin_Bottom + DRAW_AreaHeight + DRAW_Margin_Top;

    double      ChartDivX = (double)ScreenWidth  / (double)NumDivsX;
    double      ChartDivY = (double)ScreenHeight / (double)NumDivsY;
    cout << "ChartArea Width (px)  =" << ChartDivX << " * " << AREA_Total_DIV  << " = " << ChartDivX*AREA_Total_DIV << endl;
    cout << "ChartArea Height (px) =" << ChartDivY << " * " << DRAW_AreaHeight << " = " << ChartDivY*DRAW_AreaHeight << endl;

    cout << "TEST 1: " << ChartDivX << " * " << 12  << " = " << ChartDivX*12 << endl;
    cout << "TEST 2: " << ChartDivX << " * " << "12.0"  << " = " << ChartDivX*12.0 << endl;

}

The output is:

ChartArea Width (px)  =26.6667 * 12 = 37.6667  <=== WHY?
ChartArea Height (px) =16.875 * 13 = 219.375
TEST 1: 26.6667 * 12 = 320
TEST 2: 26.6667 * 12.0 = 320

I don't understand why i get that 37.6667, but the right result on the second multiply.

Parduz
  • 662
  • 5
  • 22
  • I'm pretty sure this will be downvoted as a stupid, maybe also as an already answered question, but i googled the web and searched here without finding an answer. Maybe my english isn't good enough for search terms, but i didn't get any clue. – Parduz May 31 '23 at 08:29
  • 6
    It's not really about multiplying `double` and `int`, you've found one very important reason to never use macros in C++. – Yksisarvinen May 31 '23 at 08:32
  • 3
    Not sure if I should close as duplicate of similar question (e.g. [What's going on with C++ macro multiplication](https://stackoverflow.com/questions/8508989/whats-going-on-with-c-macro-multiplication)) or answer... – Yksisarvinen May 31 '23 at 08:34
  • 1
    @Parduz Use contant variables and forget about macros, and the problem will vanish :) – Fareanor May 31 '23 at 08:36
  • 2
    ChartDivX*AREA_Total_DIV expands to ChartDivX*1+1+4+1+4+1 – Oersted May 31 '23 at 08:36
  • 1
    BRACKETS! Geez .... :( – Parduz May 31 '23 at 08:37
  • i knew it was stupid. Should i delete this question? – Parduz May 31 '23 at 08:38
  • 7
    @Parduz Whether or not you should delete this question is up on you. But what you really should do is stop using macros when what you really need is contant variables. It will be beneficial for you in the long run (and for the people you are working/will work with) – Fareanor May 31 '23 at 08:47
  • 3
    Making mistakes is not stupid, what is stupid is not learning from them :-) For instance, try @Fareanor advice and your mistake will become useful. – Oersted May 31 '23 at 09:01
  • 1
    Just about *'never use macros'* – that's actually a bit too strict… You can do really cool stuff with macros, things really difficult, sometimes even impossible to achieve without (just thinking about X-macros…) – solely: *if* there are valid alternatives (not requiring you to jump over the moon to achieve the same) then *do* prefer these! Actually that's just the same with `goto` ;) – Aconcagua May 31 '23 at 09:08
  • 1
    Side note: About [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)… – Aconcagua May 31 '23 at 09:11
  • If you still need to write macros for whatever reason you might get used to some patterns, e.g. on calculations *always* enclosing all the arguments on every usage just as well as the entire expression with parentheses (would have saved you here – but still prefer constants), or if you need multiple statements enclose them with a one-time loop: `#define FOO() do { doSomething(); doSomethingElse(); } while(0)` – this pattern will prevent errors by lacking braces of branch or loop bodies like `if(x) FOO();`. – Aconcagua May 31 '23 at 09:28
  • Then again, though, often a better pattern is writing some (inline?) function and have the macro just as a facade to, doing the stuff that *cannot* be done by the function (imagine a logging facility: `#define logError(...) doLog(Type::Error, __FILE__, __LINE__, __VA_ARGS__) template void doLog(Type type, char const* file, size_t line, char const* format, Parameters ... p);` – Aconcagua May 31 '23 at 09:32
  • If we go for macro advices and technics (but don't go too deep ;-) ): https://jadlevesque.github.io/PPMP-Iceberg/ – Oersted May 31 '23 at 09:44
  • Any time you define a macro as an expression and don't put the expression into parentheses you are going to run up against unexpected operator precedence problems like this. But `AREA_Total_DIV` should certainly be a `const` variable here. – user207421 Jun 06 '23 at 10:12

1 Answers1

-1

The problem with (ChartArea Width(px) = 37.6667) would be due to the fact that the screen width is divided into certain number of parts. In your example the total width is 480px and there is also 26.66px in each horizontal division. So multiplying this value we have a total of 12 divisions and obtaining 320px.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31