Afoak
Afoak

Reputation: 13

Printing powers of numbers and adding them all together

function obliczTo() {
  var bet = document.forms["oblicz"]["bet"].value;
  var kol = document.forms["oblicz"]["kolejki"].value;

  var bankRoll = bet * Math.pow(2.1, kol)
  document.write('Potrzebujesz: ' + Math.ceil(bankRoll))
}
<form name="oblicz" onsubmit="return obliczTo()" method="post" required>
  Bet: <input type="text" name="bet"> Ile kolejek: <input type="text" name="kolejki">
  <input type="submit" value="Submit">
</form>

I want to print every power in html and add all of them together and print that as bankRoll. for ex

bet = 10
kol = 5

in html:

21
44.1
92.61
194.481
408.4101

Bank Roll: 760.6011

And I want to print each individual output and show their accumulated sum as "Bank Roll".

Upvotes: 1

Views: 188

Answers (2)

Carsten Massmann
Carsten Massmann

Reputation: 28206

By using the geometric series summation formula you can simplify your algorithm in the way that you can directly calculate the sum of any series without having to step through the individual exponentiation steps:

where S is the total sum, a is the starting amount, q is the factor and n the highest exponent. I modified the formula here slightly: I subtracted the initial amount a from it, as you don't seem to want it included in the summation. So you end up with this modified summation formula:

const geomSum=([a,q,n])=>// (a*(q**(n+1)-1)/(q-1)-a).toFixed((n||6)-1),
                            (a*(q**(n+1)-q)/(q-1)  ).toFixed((n||6)-1),
      res=document.getElementById('res'),
      v=[].slice.call(document.querySelectorAll('input'));
function calc(){res.textContent=geomSum(v.map(e=>+e.value));}
document.querySelector('form').oninput=calc;
calc();
<form>
 <input name="a" placeholder="start value" value="10"><br>
 <input type="number" name="q" placeholder="factor" value="2.1"><br>
 <input type="number" name="n" placeholder="exponent" value="5">
</form><br><br>
<div id="res"></div>

Upvotes: 1

Lionel Rowe
Lionel Rowe

Reputation: 5926

First off, note that JavaScript numbers are floating point, and floating-point arithmetic with fractions is often imprecise. For example:

Math.pow(2.1, 4)
// should be 19.4481
// actually yields 19.448100000000004

Math.ceil rounds up to the nearest integer, which won't work for what we want here - Math.ceil(19.448100000000004) gives 20.

Here's one (kinda hacky) way of dealing with it that should work for our use case, as long as kol doesn't get very high:

const round = n => Number(n.toPrecision(12))

Now, you need to loop through numbers 1..kol, printing and summing as you go. You can use a for loop for this.

const form = document.forms.oblicz
const output = document.querySelector('#output')

const round = n => Number(n.toPrecision(12))

const clearOutput = () => output.textContent = ''
const appendLineToOutput = str => output.textContent += `\n${str}`

form.addEventListener('submit', e => {
  e.preventDefault()
  
  clearOutput()

  const bet = Number(form.bet.value)
  const kol = Number(form.kolejki.value)

  let bankRoll = 0

  for (let i = 1; i <= kol; ++i) {
    const val = round(bet * Math.pow(2.1, i))

    appendLineToOutput(val)

    bankRoll = round(bankRoll + val)
  }

  appendLineToOutput(`Potrzebujesz: ${bankRoll}`)
})
<form name="oblicz" required>
  Bet: <input type="text" name="bet" value="10"> Ile kolejek: <input type="text" name="kolejki" value="5">
  <input type="submit" value="Submit">
</form>

<pre><output id="output"></output></pre>

Note that I've used document.querySelector and textContent here, not document.write. document.write is generally considered to be deprecated, because it clears the entire document if the page is already loaded.

Upvotes: 0

Related Questions