I can’t divide with a vector element

Asked

Viewed 282 times

2

I made a code to simulate the Monty Hall paradox, so that I can simulate 1000 times the results and write the statistics. However, I cannot divide an element of an int array by an int, every time I run the program, when it reaches the division, the program crashes and has to be closed:

void main(){
    int PORTAS [] = {0, 0, 0}; 
    int CAR, ESC, NUM, DECISAO, AUX;
    float VIT, DER; 
    int ESTAT [] = {0, 0, 0};   // {Tentativas, vitórias, derrotas}

    VIT = ( ESTAT[2] / NUM ) * 100; // Porcentagem de vitórias  *ERRO*
    DER = ( ESTAT[3] / NUM ) * 100; // Porcentagem de derrotas  *ERRO*
}

I also tried to write how:

VIT = ESTAT[2]/ESTAT[1]*100;
DER = ESTAT[3]/ESTAT[1]*100;

But in this way, the result is always 0.

If necessary to help me, I will put the full code, which includes at the beginning a brief explanation of the game. If you don’t think it’s necessary, ignore the code below:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <math.h>

/*Paradoxo de Monty Hall
*Atrás de uma porta, de três no total, é escondido um carro
*e nas outras duas, uma cabra. No jogo, o jogador escolhe uma
*porta e então é revelada outra porta que contenha uma cabra.
*O jogador tem então a opção de escolher entre manter a escolha
*ou trocar de porta. Esse programa simula esse jogo, de modo que 
*a porta seja mantida ou trocada em todas as tentativas, para
*motivos estatísticos.*/

void main(){
    setlocale (LC_ALL, "");

    int PORTAS [] = {0, 0, 0};  // 0 - a porta contém uma cabra; 1 - a porta contém o carro 
    int CAR, ESC, NUM, DECISAO, AUX;
    float VIT, DER; 
    int ESTAT [] = {0, 0, 0};   // {Tentativas, vitórias, derrotas}

    printf("1 para trocar todas, 0 para manter todas: ");
    scanf ("%d", &DECISAO);
    printf ("Digite o número de repetições: "); // Recomendável 10, 100 ou 1000.
    scanf ("%d", &NUM);

    do{
        CAR = rand () %3;   // Randomiza a porta que recebe o carro.
        PORTAS [CAR] = 1;   

        ESC = rand () %3;   // Randomiza a escolha da porta.

        if ( DECISAO == 1 ){    // Se foi escolhido trocar todas as vezes.
            if ( PORTAS [ESC] == 1 ){   // Porta escolhida contém o carro.
                for ( AUX = 0; AUX < 3 ; AUX++ ){
                    if ( PORTAS [AUX] != 1 && AUX != ESC ){
                        ESC = AUX;      //Mudança de porta
                        AUX = 3;    // Para quebrar o 'For'
                        ESTAT [3] += 1;
                    }
                }
            }

            if ( PORTAS [ESC] == 0){    //Porta escolhida contém uma cabra.
                ESC = CAR;  // Pois sendo a porta errada, e tendo a outra errada sido revelada, só sobrou a correta.
                ESTAT [2] += 1;
            }
        }

        if ( DECISAO == 0){     //Caso tenha sido escolhido manter todas as vezes.
            if ( ESC = CAR ){
                ESTAT [2] += 1;
            }
            else{
                ESTAT [3] += 1;
            }
        }

        NUM--;
        ESTAT [1] += 1;
    } while ( NUM > 0);

    VIT = ( ESTAT[2] / NUM ) * 100; // Porcentagem de vitórias  *ERRO*
    DER = ( ESTAT[3] / NUM ) * 100; // Porcentagem de derrotas  *ERRO*

    ( DECISAO == 1 ) ? printf ("\n\n\n\tTrocando de porta todas as vezes: \n\n") : printf ("\n\n\n\tMantendo a porta todas as vezes: \n\n");
    printf ("Número de tentativas: %d\n", ESTAT [1]);
    printf ("Número de vitórias: %d, %d%% do total.\n", ESTAT [2], VIT);
    printf ("Número de derrotas: %d, %d%% do total.", ESTAT [3], DER);

    getch();
}
  • And what’s the problem? It’s giving division error by 0?

  • I forgot to include the error, it was bad. In the first mode, the program simply crashes, and in the second, the result is always 0. I will include in the question.

  • 3

    Initializes all elements of PORTAS with 0 And then, inside the loop, you’re putting 1 ... but you never go back 0 and so behind every door there’s always a car. Oh! and stop using more!

  • Thanks, I hadn’t noticed this. And isn’t it recommended to use uppercase? I started using because I thought it best to visually identify the variables.

  • 1

    @Douglasmarques It is usually agreed that minusculas are for methods/variables, MAIUSCULAS for constants and PrimeirasLetrasMaiusculas for types (struct, typedef, or in the languages that support, classes). You can escape the convention, but it makes it difficult for other people to understand your code, so I don’t recommend.

  • @Douglasmarques Take a look at [tour]. You can accept an answer if it solved your problem. You can vote for every post on the site as well. Did any help you more? You need something to be improved?

  • Note that as you have declared integer variables the operations will be done with integer mathematics and only in the assignment the result will be converted to real. Use a cast to force floating point operation.

Show 2 more comments

2 answers

1

I don’t know what the goal is but this is basic math. The code is running when NUM is 0 and this operation is not possible according to the mathematical rule.

Probably shouldn’t wear one array For this specific question problem, three variables would be more readable. This is just one of the things that makes code difficult to read and understand. In addition it is using elements 1, 2 and 3 when it should be 0, 1 and 2.

The second way may not cause the problem but is it what you want? You can’t keep including random variables in the expression to see if it works. And this used is very random, it doesn’t make any sense. It has to do what it needs. And only you know this.

I think it should be like in the first form, but keeping the initial value of the variable. It cannot reuse variables. I created a new variable called repeticoes to store the value and make the division correctly.

Actually the code is full of errors. It is no use trying to solve complex problems when you do not know the basics of programming. After solving several compilation errors it seems that worked, but I do not guarantee that you are doing what you want. So there must be problems that go beyond what is in the question.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main() {
    int PORTAS[] = {0, 0, 0};  // 0 - a porta contém uma cabra; 1 - a porta contém o carro 
    int ESTAT[] = {0, 0, 0};   // {Tentativas, vitórias, derrotas}
    int repeticoes;
    int DECISAO;
    printf("1 para trocar todas, 0 para manter todas: ");
    scanf ("%d", &DECISAO);
    printf ("Digite o número de repetições: "); // Recomendável 10, 100 ou 1000.
    scanf ("%d", &repeticoes);
    int NUM = repeticoes;
    do {
        int AUX;
        int CAR = rand () %3;   // Randomiza a porta que recebe o carro.
        PORTAS[CAR] = 1;   
        int ESC = rand () %3;   // Randomiza a escolha da porta.
        if (DECISAO == 1) {    // Se foi escolhido trocar todas as vezes.
            if (PORTAS[ESC] == 1 ) {   // Porta escolhida contém o carro.
                for (AUX = 0; AUX < 3 ; AUX++) {
                    if (PORTAS[AUX] != 1 && AUX != ESC) {
                        ESC = AUX;      //Mudança de porta
                        AUX = 3;    // Para quebrar o 'For'
                        ESTAT[2] += 1;
                    }
                }
            }
            if (PORTAS[ESC] == 0) {    //Porta escolhida contém uma cabra.
                ESC = CAR;  // Pois sendo a porta errada, e tendo a outra errada sido revelada, só sobrou a correta.
                ESTAT[1] += 1;
            }
        }
        if (DECISAO == 0) {     //Caso tenha sido escolhido manter todas as vezes.
            if (ESC == CAR ) ESTAT[1] += 1;
            else  ESTAT[2] += 1;
        }
        NUM--;
        ESTAT[0] += 1;
    } while (NUM > 0);
    float VIT = (ESTAT[2] / repeticoes) * 100; // Porcentagem de vitórias  *ERRO*
    float DER = (ESTAT[3] / repeticoes) * 100; // Porcentagem de derrotas  *ERRO*
    (DECISAO == 1) ? printf("\n\n\n\tTrocando de porta todas as vezes: \n\n") : printf("\n\n\n\tMantendo a porta todas as vezes: \n\n");
    printf("Número de tentativas: %d\n", ESTAT[0]);
    printf("Número de vitórias: %d, %f%% do total.\n", ESTAT[1], VIT);
    printf("Número de derrotas: %d, %f%% do total.", ESTAT[2], DER);
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

I improved the code but not everything.

  • I really didn’t notice that the NUM was 0 at the end. As for the second form, they are not random, the first element of the ESTAT array is the repetition count, the second and the number of wins, so the second over the first is the fraction that indicates the wins, for example. As for the other errors, please tell me. The only part that went wrong was in my compilation, the rest went exactly as desired. And really, I do make a lot of basic mistakes, because it’s not my field and I started studying just a few weeks ago.

  • It may be, but the code is so confused that you can’t understand it. As I said, this array nor should there be, it may seem that there is a relationship between them, but at bottom there are 4 different pieces of information. I fixed the errors, just analyze my code. First you need to lay brick and then try to build a house. Believe me, this never works.

  • There are few errors left in the modified version: 1) the doors are never reset to 0, so eventually all will contain the car; 2) the first if is unnecessarily complex, if the door contains the car and the player chose to trade, he will lose, do not need this loop to know that (but despite that he seems to be correct, so did not move); 3) missed an Else after this if; 4) at the time to make the statistics, the division was whole, so it always came to zero. modified example working as expected

  • P.S. Personally I didn’t find the code so confusing, I found it quite easy to understand considering it was written by a beginner (except for that unnecessary loop involving AUX). On the other hand, I already had prior knowledge of Monty Hall, so I already knew what to expect, if it was an unknown domain I don’t know if my impression would be the same or not...

  • @mgibsonbr is confusing to read and accompany by giving bad names. It is not complex, only poorly written.

0

I also tried to write how:

VIT = ESTAT[2]/ESTAT[1]*100;
DER = ESTAT[3]/ESTAT[1]*100;

There are two problems here: first, in C the arrays are indexed from zero, not from one, so that the first element has index 0, the second index 1 and the third index 2. Access the index 3 how are you doing is invalid for a array size 3, and the result is undefined (because you are accessing an arbitrary memory region, which may even be outside the scope of your program).

The second problem is that the entire division will always give an entire result, even if the variable where you intend to store the result is float. If the dividend is less than the divisor then the result will always be zero (as you observed). Fixing both problems we have:

 VIT = 1.0f*ESTAT[1]/ESTAT[0]*100; // Ao multiplicar primeiro por 1.0f
 DER = 1.0f*ESTAT[2]/ESTAT[0]*100; // o operando passa a ser um float

Already his first attempt (as NUM) was flawed because you’ve been decreasing NUM in his loop down to zero. When trying to divide by zero, naturally there would be a problem...

P.S. I didn’t revise the full code - because Maniero has already done it - but after the correction of the main errors we arrived to that final result (the result of which corresponds to the expected, statistically speaking). Some recommendations:

  • Do not use full-name variables in upper case, as this notation is traditionally used to represent constants only;
  • Document your variables, and try to give them self-descriptive names. I personally had no trouble understanding what it was CAR[ro] and ESC[look], but this is due to the previous knowledge I had from Monty Hall, other people may have more difficulty relating the variables to the elements of the domain;
  • If two conditions are mutually exclusive, I suggest using else even if you don’t think it’s necessary. In this code:

        if ( PORTAS [ESC] == 1 ){   // Porta escolhida contém o carro.
           ...
        }
    
        if ( PORTAS [ESC] == 0){    //Porta escolhida contém uma cabra.
           ...
        }
    

    you didn’t use the else, and so he ended up entering the second if even after having entered the first (because this modified ESC) - causing the number of hits plus the number of errors to exceed the number of attempts...

    Two ifs in a row without else should only be used if there is a chance of entering: a) only in the first; b) only in the second; c) in both; d) in either.

  • I saw that you tried to simulate the change of choice (reassigning ESC), but in this case this is unnecessary - if he chose right, he will lose, if he chose wrong, he will win, there is no need to simulate anything else. Anyway, your loop who uses AUX is correct, although a bit confused (by the way, you knew you could leave early from a loop using break?).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.