Math.Running defining minimum and maximum values other than 0

Asked

Viewed 166 times

4

I’m trying to set the minimum and maximum value, using Math.random() * (max - min) + min;, for example, informing on the Html page the minimum = 10 and the maximum = 20, but the results are always between 0 and 9 only, that is, it is not obeying the given parameter.

If I define the numbers in the code, for example: 5 + (Math.random() * 15);, results are 5 to 19, which makes sense, considering that 15 numbers would be drawn, starting from 5.

But I need to inform the minimum value and the maximum value that should be drawn.

I tried to use too min + (Math.random() * max);, still stating on the html page the minimum = 10 and the maximum = 20, the results are numbers starting with 10 and alternating the last two digits from 0 to 19. for example, 1019,106,1015,103... and so on, still not respecting the defined parameter.

Can anyone help me? Where I’m going wrong?

Follows the code:

function sortear(){
    var min = document.getElementById("minimo").value;
    var max = document.getElementById("maximo").value;
    
    var sorteio = Math.floor(Math.random() * (max - min) + min);
    
    document.getElementById("resultado").innerHTML = sorteio;
}
<div>
  <p>
    Insira o valor mínimo:
    <input type="number" name="minimo" id="minimo">
  </p>
</div>
<div>
  <p>
    Insira o valor máximo:
    <input type="number" name="maximo" id="maximo">
  </p>
</div>
<div>
  <button onclick="sortear()">Sortear</button>
</div>
<div>
  <h1 id="resultado"></h1>
</div>

1 answer

4

This is happening because you are not passing numerical values, but yes strings that in some cases (given the coercive behavior of Javascript) will be converted, but in others, not.

Thus, as the property value always returns a string, you must, before using them, convert them to the appropriate type:

function sortear(){
    var min = parseInt(document.getElementById("minimo").value, 10);
    var max = parseInt(document.getElementById("maximo").value, 10);
    
    var sorteio = Math.floor(Math.random() * (max - min) + min);
    
    document.getElementById("resultado").innerHTML = sorteio;
}
<div>
  <p>Insira o valor mínimo: <input type="number" name="minimo" id="minimo"></p>
</div>
<div>
  <p>Insira o valor máximo: <input type="number" name="maximo" id="maximo"></p>
</div>
<div>
  <button onclick="sortear()">Sortear</button>
</div>
<div>
  <h1 id="resultado"></h1>
</div>

In this case, we use the parseInt to perform the conversion of string for number. Other options for this conversion are builder Number or parseFloat. You can also use the unary operator +, but I personally don’t like this last option.

Now I will actually explain what was going on when you were using the wrong types. First, we need to analyze the expression to be interpreted by Javascript:

Math.floor(Math.random() * (max - min) + min);

Supposing max be it "15" and min be it "5" (note that both are strings), we can assume the following:

Math.floor(Math.random() * ("15" - "5") + "5");

First, Javascript will evaluate the subtraction within the parentheses, which give preference to this evaluation. As the operator -, in Javascript, means arithmetic subtraction exclusively, the two operands are correctly converted to type number before the operator performs the subtraction.

Once we have the result of the previous subtraction (10 - note that now it is a number), we will multiply with the value returned by Math.random, which is also a number.

Finally, the product will be concatenated (+) with the value of min (which was to be a sum). This is because, in Javascript, the binary operator + may have different meanings depending on the type of your operands. I explain this better in this question: How the "+" operator works in Javascript?.

So, keeping the values max and min as string, we will have the following evaluation step by step:

  1. Math.floor(Math.random() * ("15" - "5") + "5");
  2. Math.floor(Math.random() * 10 + "5");
  3. Math.floor(0.8879528248948558 * 10 + "5"); - assuming that Math.random return 0.8879528248948558.
  4. Math.floor(8.879528248948558 + "5");
  5. Math.floor("8.8795282489485585"); - Note that the "5" was concatenated at the end of the product.
  6. 8Math.floor, according to the specification, converts the type to number automatically.

So, as you can see, this automatic type coercion of Javascript is really confusing and full of subtleties that can affect the robustness of the code. Therefore, it is always ideal that you convert the guys explicitly for the numeric value if you want to work with mathematical operations.

Browser other questions tagged

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