0

I am newer to the C# program and I am trying to figure out how to just display the last value of my for loop.

I have tried looking online, but there are only results showing how to display the last iteration of a foreach loop.

I want to be able to use the last value of my for loop, and create a new loop based upon that number. Here is my current code:

int x = a * b;

for (int i = 0; Math.Pow(i,2) < x; i++)
{
    Console.WriteLine(Math.Pow(i, 2));
}

Example: a=8, b=10. then x=80. Currently it's writing out every value up to 64, which would be 8^2. How do I get it to just display the 64?

Any suggestions? Should I be using a different loop?

swim247
  • 55
  • 5

6 Answers6

2

Here's a version that only computes the exponent once per iteration:

int a = 8, b = 10;
int x = a * b;

int result = 0;
for (int i = 0, temp = 0; temp < x; temp = (int)Math.Pow(i,2))
{
    i++;
    result = temp;
}
Console.WriteLine(result);

The important things are moving the line to output the result to after the loop, and keeping a value for the previous result that will still be in scope.

Fiddle with it

Another option that's much more direct:

int a = 8, b = 10;
int x = a * b;

int y = (int)Math.Floor(Math.Sqrt(x));
Console.WriteLine(y * y);

No loop required. Not even Math.Pow(). But it will get the right result, and in O(1) time (depending on your interpretation of Math.Sqrt()).

Fiddle with it

Or as a one-liner:

Console.WriteLine((int)Math.Pow(Math.Floor(Math.Sqrt(x)), 2));
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
0

Another approach is to generate the sequence then select the one you want

public static IEnumerable<(int n, double pow)> ToThePowerOf(int start, int power)
{
    while (true) yield return (start, Math.Pow(start++, power));
}
private static void Calculate(int a, int b)
{
    var x = a * b;
    var highest = ToThePowerOf(0, 2).TakeWhile(v => v.pow < x).Last();
    Console.WriteLine($"{highest.n}^2 = {highest.pow} < {x} = {a}*{b}");
}

or you can print them all like

ToThePowerOf(0, 2).TakeWhile(v => v.pow < x).Select(v => v.pow).ToList().ForEach(Console.WriteLine);
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
0

Math.Pow is slow. Eliminate double precision computation wherever possible.

        // for testing
        int a = 10; 
        int b = 20; 

        int x = a * b;

        Console.WriteLine("Done");
        long kPowerPrev = -999; // or whatever
        long kPowerCur = 0;
        int j = 0;
        while (true)
        {
            kPowerPrev = kPowerCur;
            // Don't use Math.Pow, it is slow, because of conversion to double.
            // so if you are raising it to an integer power, it is better to multiply by hand
            // The last time I measured, hand multiplication beat Math.Pow when your power is 5 or less
            j++;
            kPowerCur = j * j;
            if (kPowerCur >= x)
            {
                Console.WriteLine(kPowerPrev);
                break;
            }
        }
        Console.WriteLine("Done");
M G
  • 47
  • 1
-1

You could brute force it easily by adding a new variable and storing the current value on it:

int x = a * b;
int finalVal;
for (int i = 0; Math.Pow(i,2) < x; i++)
{
    finalVal = Math.Pow(i, 2);
    Console.WriteLine(finalVal);
}
//You can use finalVal here and will always be the last value from the loop.
dacaballero
  • 7
  • 1
  • 2
-1

My first guess would have been brute forcing it like dacaballero. But that was solved. And chances are good it is not even a performance drain. The JiT and other Optimisation are pretty good and might figure out "hey, that value is only actually read once after the last loop. No point doing that line before then". Indeed without the output, there is a decent chance it will cut the whole loop out.

And depending on what you are doing in the long run, a different loop might be better. I like to use the while/do while with a bool control variable.

int x = a * b;
int finalValue = 0;
bool continueLoop = true;
int i = 0; //Counter variable

do{
  //Let us only do that one once
  int current = Math.Pow(i,2);

  if(current < x){
    //Nothing to do here.
    //I just prefer a empty if/else over a NOT modifier
  }
  else{
    finalValue = current;
    continueLoop = false;
  }
  i++;
}while(continueLoop)

Of course you also asked about using that variable for the next loop. Now you can nest loops, but I do find they get a bit too hard to read to nest even 2 loops. So small modification:

  • make above loop or the simple for variant a function. call it innerLoop.
  • It takes one input - the int value for x/the endpoint
  • it returns the finalValue as return value.

Call the function in this loop:

int endpoint = a * b;

do{
  endpoint = innerLoop(endpoint);
  Console.WriteLine(endpoint);
}while(true); //you gave no condition, so I infinite loop.
Christopher
  • 9,634
  • 2
  • 17
  • 31
  • 1
    *I just prefer a empty if/else over a NOT modifier* => this generates unclean code, I think. –  Nov 08 '19 at 03:22
  • @OlivierRogier And I find the NOT unlcean and hard to read. It it maters, it is *trivial* to replace it with a NOT. – Christopher Nov 08 '19 at 05:34
-2

Here is the solution for your problem:

int x = a * b;
int lastValue;
for (int i = 0; Math.Pow(i,2) < x; i++)
{
    lastValue= Math.Pow(i, 2);
}
Console.WriteLine(lastValue);
lamtacvu
  • 675
  • 1
  • 7
  • 14
  • Accidentally posting the same as another poster can happen. But not with 25 minutes difference. – Christopher Nov 08 '19 at 03:11
  • @Christopher It is not the same. I saw the question changed and it is different when asker only want to print the last value, not any value in each iteration – lamtacvu Nov 08 '19 at 03:15
  • Changing the line of a WriteLine used for debug/demonstration purposes is not a relevant change. I doubt you will get any upvotes with it. – Christopher Nov 08 '19 at 03:18