0

So here's the current implementation of my power function.

pow(x, n) int x, n;
{
    int r = 1;
    int i;

    for (i = 0; i < n; i++)
        r *= x;

    return (r);
}

The problem is how it only works for whole numbers & doesn't work with floats like pow(4, .5).

Of course, I've already tried changing everything to double & I know how a standard library function exists. Also I've seen Floating point exponentiation without power-function, but none of the solutions were working nor what I wanted.

Here is the version, where I used doubles.

double pow(x, n)
double x, n;
{
    double r = 1.;
    int i;

    for (i = 0; i < n; i++)
        r *= x;

    return (r);
}

It returns 1., when I use it as pow(4., .5).

  • 5
    `pow(x, n) int x, n;` is a *very* old function definition syntax. Are you really using a compiler that old? – Steve Summit Feb 17 '23 at 19:47
  • Please show the version you tried using `double`. Since you know why the version using `int` didn't work, there's little point working on that version. The problem may simply be that you neglected to declare your `pow` function as returning `double`. – Steve Summit Feb 17 '23 at 19:48
  • @SteveSummit I did indeed make sure that my return type is also a `double` – KianFakheriAghdam Feb 17 '23 at 19:50
  • KianFakheriAghdam Show us! – Steve Summit Feb 17 '23 at 19:51
  • 1
    Re “one of the solutions were working nor what I wanted”: Specify what you want. Telling us the answers in that question were not what you want does not tell us what you do want. Explain why they were inadequate. Also, do you have some grasp of how complicated a good `pow` function is? Do you have some idea how to approximate the logarithm of a value? – Eric Postpischil Feb 17 '23 at 19:55
  • @SteveSummit I updated it with what you wanted – KianFakheriAghdam Feb 17 '23 at 19:58
  • So now we can say: Repeated multiplication will only work to compute *integer* powers. `pow(4., .5)` wants the square root, but you've got no code to do that. – Steve Summit Feb 17 '23 at 19:58
  • @EricPostpischill I want a solution that doesn't require embedding assembly & use of other standard library functions – KianFakheriAghdam Feb 17 '23 at 19:59
  • Floating point power functions generally make use of the fact that a^b = exp(log(a^b)) = exp(b*log(a)). They may do some tricks to improve accuracy, adjust the range, etc., but that's the general approach. – Tom Karzes Feb 17 '23 at 20:00
  • 3
    *I want a solution that doesn't require use of other standard library functions* In that case you are probably going to have to implement your own `ln()` and `exp()` functions, and then implement `pow(x, y)` using the standard identity `exp(ln(x) * y)`. This will give you decent results for ordinary cases, although making it perfectly general and maximally accurate is a lot of work. Implementing your own `ln()` and `exp()` functions will be a challenge also. There's a straightforward Taylor expansion for `exp`, but it works well only over a rather narrow range of values. `ln` is harder. – Steve Summit Feb 17 '23 at 20:00
  • ... to which [this answer](https://stackoverflow.com/a/3519054/2402272) to the question you linked speaks. A bit. – John Bollinger Feb 17 '23 at 20:03
  • @JohnBollinger I've already read that – KianFakheriAghdam Feb 17 '23 at 20:05
  • @SteveSummit exactly as you stated. I might've had problems with implementing those – KianFakheriAghdam Feb 17 '23 at 20:06
  • 1
    @KianFakheriAghdam: Yes, you read it, so what? It tells you pow(a, b) can be implemented as exp(b log a), and it points to information about implementing exp and log. What more do you need? Do you know about Taylor series? Do you know about formats used to represent floating-point numbers? Can you separate a floating-point number into its exponent and significand? A full-featured high-quality pow implementation requires a lot of code, analysis, calculation, and proof. Nobody will write the whole thing for you. You can hope people will step you through the parts, but there is much to learn. – Eric Postpischil Feb 17 '23 at 20:07
  • The other classic problem with `exp(ln(x) * y)` is that `(int)pow(2., 3.)` is usually 7. – Steve Summit Feb 17 '23 at 20:08
  • Don't let Eric scare you off with talk of "separating a floating-point number into its exponent and significand". You *can* write `exp()` and `ln()` yourself, starting perhaps with some of the infinite series mentioned in the Wikipedia articles. (That's what I did.) Your first implementations will be terrible, and they won't work for operands bigger than 5 or 10, but you'll learn a lot, and after you've got it barely working, if you've still got energy you can start figuring out how to make it better. – Steve Summit Feb 17 '23 at 20:13
  • @SteveSummit what do you mean? if not even that will give me the full answer, then what should I do? – KianFakheriAghdam Feb 17 '23 at 20:13
  • I got even more scared by how it won't work for bigger ooerands – KianFakheriAghdam Feb 17 '23 at 20:15
  • 1
    *What should I do?* It depends on the situation. Is someone paying you to write a production-quality version of `pow()`? If so, I'm afraid you're doomed. But if your goal is just to start learning about floating point, *really* learn about floating point, then this is a great learning exercise — but not an easy one! (I would rate it as intermediate to advanced.) – Steve Summit Feb 17 '23 at 20:16
  • Asking how to calculate powers seems like a bit of a math problem more than a programming problem. I don't know how to calculate 0.2^0.3 *by hand*, but if I did, I could translate that into a computer program. – user253751 Feb 17 '23 at 20:17
  • And the way to approach any hard problem is to break it down into smaller steps. First write your own exp(), comparing its output to the standard one. If it works okay for operands less than 5, but not so well for bigger operands, that's okay for the moment — and if the threshold between "works well" and "works bad" is higher, so much the better! Then you can work on `log()`, again comparing it to the standard version, focusing again on small arguments, say less than 10. – Steve Summit Feb 17 '23 at 20:23
  • And if you can get them both working, then you can do little problems like `pow(4., 0.5)` and `pow(2., 3.)`. And you'll have learned a lot! You should totally go for it. I am not trying to discourage you. *After* you've got a toy version working, you'll be in a position to explore ways to make it better. But those ways are black magic to you now, and totally discouraging, which is why I suggest not worrying about them (yet). – Steve Summit Feb 17 '23 at 20:24
  • Re “what should I do?”: Answer questions. Tell us what you do and do not know so that we know where to tell you to start. Do you know what a Taylor series is? – Eric Postpischil Feb 17 '23 at 20:24
  • @KianFakheriAghdam `double pow(double base, double y)` is a challenging function to write well. You can get quick weak answers or well thought out ones that take time. How soon do you want an answer? – chux - Reinstate Monica Feb 17 '23 at 20:26
  • You didn't ask a question?!?!? – ikegami Feb 17 '23 at 20:43
  • 1
    One thing to keep in mind about accuracy is that, since log and exp are not linear functions, for certain ranges the values are compressed, and for others they are expanded. The compressed ranges are a problem, since in those ranges precision is lost. For example, if you look at the difference between log(1000000) and (1000001), it is a lot smaller than 1, if in fact the difference is even present in the logs. To compensate for this, you can do things to adjust the range. For example, x^y = (1/x)^(-y). So if x > 1, this transformation might help. But this introduces other risks. – Tom Karzes Feb 17 '23 at 21:38

0 Answers0