Implementing some pseudocode in python

  • Context: Python 
  • Thread starter Thread starter Mr Davis 97
  • Start date Start date
  • Tags Tags
    python
Click For Summary

Discussion Overview

The discussion revolves around implementing pseudocode in Python, specifically focusing on translating a C-style for loop into Python's looping constructs. Participants explore the challenges of using floating point numbers in loops and discuss various approaches to achieve the desired functionality, including the use of while loops, generators, and explicit enumeration of values.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant expresses the need to implement pseudocode that uses a C-style for loop, questioning how to adapt it for Python's foreach style.
  • Another participant suggests that using the built-in range() function is not suitable for floating point numbers and recommends writing a custom generator or using numpy.linspace.
  • A different viewpoint proposes using a while loop instead, noting potential issues with floating point precision in such loops.
  • Some participants highlight the problems with floating point arithmetic, indicating that simple additions may not yield expected results due to representation errors.
  • One participant advocates for explicitly enumerating the specific rates (0.05, 0.10, 0.15) to avoid complications with floating point arithmetic, arguing this is a clearer and more "pythonic" approach.
  • Another participant raises a concern about scalability when dealing with a larger number of percentages, questioning how to handle such cases without running into floating point issues.
  • A participant unfamiliar with Python suggests using an integer loop variable to derive floating point values, presenting a method that could be applied in other programming languages.
  • One participant mentions that for large datasets, using generators can be an efficient solution to mitigate floating point accumulation errors.

Areas of Agreement / Disagreement

Participants do not reach a consensus on the best approach to implement the pseudocode. Multiple competing views remain regarding the use of while loops, explicit enumeration, and the potential use of generators or libraries like numpy.

Contextual Notes

Participants note limitations related to floating point precision and the representation of real numbers in computing, which may affect the execution of loops and calculations. The discussion includes various assumptions about the context in which these implementations would be used.

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?
 
Technology news 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.
 

Similar threads

  • · Replies 16 ·
Replies
16
Views
3K
  • · Replies 0 ·
Replies
0
Views
2K
  • · Replies 4 ·
Replies
4
Views
6K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 6 ·
Replies
6
Views
2K
Replies
3
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K
Replies
12
Views
7K
  • · Replies 1 ·
Replies
1
Views
5K
  • · Replies 14 ·
Replies
14
Views
5K