Implementing some pseudocode in python

  • Context: Python 
  • Thread starter Thread starter Mr Davis 97
  • Start date Start date
  • Tags Tags
    python
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
7 replies · 3K views
Mr Davis 97
Messages
1,461
Reaction score
44
I need to implement the following pseudocode in Python:

Code:
N=5            #where N is number of years
    For (rate = 0.05, rate <= 0.15, rate = rate + 0.05)
      For (principal=10000, principal <=15000, principal=principal+1000)
         simple = principal * (1 + rate * N) #where N is number of years
         compound = principal * (1 + rate) ^ N
         print simple + “ “ + compound
      EndFor
    EndFor

However, this psudocode uses the for loop in the style of a C language. Python uses a foreach type loop, which takes a variable and iterates over a list. We typically use `range()` for this for the list, but this only takes integers as arguments, while the for loop I am trying to implement needs to take floating point numbers. Is there any simple way in which I can use a typical Python for loop to implement this? Or will I have to fall back on using a while loop with a counter variable?
 
on Phys.org
You can't use the built-in range() for this without obfuscating contortions. You can write your own generator for this task, with the usual caveats about floating point comparisons. Alternatively, if numpy is available you can use numpy.linspace. (Don't avoid numpy feeling that it isn't standard, it's ubiquitous for Python numeric work. Furthermore you will usually get better performance from it than by rolling your own solutions.)
 
Integrand said:
You can't use the built-in range() for this without obfuscating contortions. You can write your own generator for this task, with the usual caveats about floating point comparisons. Alternatively, if numpy is available you can use numpy.linspace. (Don't avoid numpy feeling that it isn't standard, it's ubiquitous for Python numeric work. Furthermore you will usually get better performance from it than by rolling your own solutions.)

So assuming that I don't want to do any of the things that you suggested, I would have to use a while loop?
 
Mr Davis 97 said:
I need to implement the following pseudocode in Python:

Code:
N=5            #where N is number of years
    For (rate = 0.05, rate <= 0.15, rate = rate + 0.05)
      For (principal=10000, principal <=15000, principal=principal+1000)
         simple = principal * (1 + rate * N) #where N is number of years
         compound = principal * (1 + rate) ^ N
         print simple + “ “ + compound
      EndFor
    EndFor

However, this psudocode uses the for loop in the style of a C language. Python uses a foreach type loop, which takes a variable and iterates over a list. We typically use `range()` for this for the list, but this only takes integers as arguments, while the for loop I am trying to implement needs to take floating point numbers. Is there any simple way in which I can use a typical Python for loop to implement this? Or will I have to fall back on using a while loop with a counter variable?
You can use a while loop.
Python:
rate = .05
while rate <= .15:
   #do stuff if rate is <= .15
   rate += .05
I should mention that because of the way floating point numbers are stored, the above loop body executes only twice, not the three times that one would expect. In most programming languages, comparison of equality of two floating point numbers is fraught with difficulty.

The following code behaves more like what one would expect.
Python:
rate = .125
while rate <= 1.0:
   #do stuff if rate is <= 1.0
   rate += .125
This loop body executes 8 times. The reason this loop works as one might expect is that all of the numbers involved (.125 and 1.0) are powers of 2 (2-3 = 1/8 = .125, and 20 = 1), and so are stored exactly. In the previous example, the numbers involved aren't powers of 2, and what is stored for each is only an approximation.
 
Mr Davis 97 said:
Code:
For (rate = 0.05, rate <= 0.15, rate = rate + 0.05)
    calculate_interests_given_rate

The above is problematic in almost every language. (Caveat: It's not a problem if you use fixed point decimal arithmetic package. But who does that, by default?) The problem is in how computers represent real numbers. It is quite possible that 0.05+0.05+0.05 will be greater than 0.15. On some computers, that for loop will only execute twice.

Is there any simple way in which I can use a typical Python for loop to implement this? Or will I have to fall back on using a while loop with a counter variable?

In this particular case, you only have three values to be examined. I myself would use
Python:
for rate in (0.05, 0.10, 0.15) :
    calculate_interests_given_rate

This says exactly what you want to do: You want to do some calculations with those three specific rates. There's no mucking around with the vagaries of floating point arithmetic, no obfuscations involving an integer loop variable multiplied by some real scale factor.

Being pythonic used to seem to mean finding the cleverest, most obscure way to do something. That was never the intent of being "pythonic". Being pythonic has always supposed to have meant using the one approach that is clearest and most obvious (at least to someone who understands python). In this case, explicitly enumerating the three rates you want to cover is about as pythonic as you can get. As a bonus, you can't do that in C or C++ without some contortions. Even with C++11, you'll need to use a dummy variable to hold those rates:
C:
double rates[] = {0.05, 0.10, 0.15};
for (auto rate : rates) {
    calculate_interests_given_rate(rate);
}
 
Last edited:
D H said:
The above is problematic in almost every language. (Caveat: It's not a problem if you use fixed point decimal arithmetic package. But who does that, by default?) The problem is in how computers represent real numbers. It is quite possible that 0.05+0.05+0.05 will be greater than 0.15. On some computers, that for loop will only execute twice.
In this particular case, you only have three values to be examined. I myself would use
Python:
for rate in (0.05, 0.10, 0.15) :
    calculate_interests_given_rate

This says exactly what you want to do: You want to do some calculations with those three specific rates. There's no mucking around with the vagaries of floating point arithmetic, no obfuscations involving an integer loop variable multiplied by some real scale factor.

Being pythonic used to seem to mean finding the cleverest, most obscure way to do something. That was never the intent of being "pythonic". Being pythonic has always supposed to have meant using the one approach that is clearest and most obvious (at least to someone who understands python). In this case, explicitly enumerating the three rates you want to cover is about as pythonic as you can get. As a bonus, you can't do that in C or C++ without some contortions. Even with C++11, you'll need to use a dummy variable to hold those rates:
C:
double rates[] = {0.05, 0.10, 0.15};
for (auto rate : rates) {
    calculate_interests_given_rate(rate);
}

In this case your idea will work well--using a list to iterate over rather than a while loop. However, what would I do in situations that call for a large number of percentages, like 1000? I couldn't possibly store them all in a list before run-time. Usually a for-loop would be used for this, but floats are imprecise... So what would I do? (I just want to know so that I don't run into the problem in the future without knowing what to do).
 
I don't know about python, but usually what you want is to use an integer as the loop argument, and derive floats from it:
C:
// For (rate = 0.05, rate <= 0.15, rate = rate + 0.05)
for (int i_rate = 5; i_rate <= 15; i_rate += 5)
   {
      float rate = i_rate /100.;
      // ...
   }
 
D H provided a nice specific solution, but if you want a general one that efficiently handles large data sets then it's back to generators. They yield successive values in a sequence without constructing the entire sequence. If you want to construct your own generator rather than use something like numpy.linspace as I suggested above (this is a solved problem), then I recommend you mitigate floating point accumulation errors by calculating at the start how many values you expect in total, then multiply the output of the builtin range() function against your step size each interation.