-3

I want to replace pow with something other than multiplication. How can i do it? THIS PROGRAM SEARCHES FOR THE ROOT OF THE SUM OF SQUARES OF ENTERED NUMBERS:

#include <stdio.h>
#include <math.h>
#define N 10000
double norm2(double a[],int n);
int main(void)
{
    double a[N]; int n;
    scanf("%d",&n);
    norm2(a,n);
    
    return 0;
}
double norm2(double a[],int n)
{
    int i=0; double sum=0;
    for(i=0;i<n;i++)
    {
        scanf("%le",&a[i]);
        if(a[i]<0.0) a[i]=-a[i];
        sum+=exp2(2*log2(a[i]));}
    printf("%le",sqrtf(sum));
    return 0;
    }
With Orxan
  • 25
  • 6
  • 2
    I guess you could square anything with repeated addition. – Emanuel P Apr 20 '21 at 20:27
  • 5
    Can you explain why you want to do this? – Retired Ninja Apr 20 '21 at 20:28
  • 4
    `exp(log(x)+log(x))` is equivalent to square – stark Apr 20 '21 at 20:28
  • i want square numbers as 1.2162e+5 and without loss of accuracy – With Orxan Apr 20 '21 at 20:31
  • @EmanuelP Would be tricky for fractional numbers. – Eugene Sh. Apr 20 '21 at 20:31
  • i try now,mr stark – With Orxan Apr 20 '21 at 20:31
  • 3
    "and without loss of accuracy" You can't. – n. m. could be an AI Apr 20 '21 at 20:33
  • mr stark, i love you, thanks you very much and others for taking the time to help me – With Orxan Apr 20 '21 at 20:35
  • yes, i already understand) – With Orxan Apr 20 '21 at 20:36
  • @WithOrxan But I hope you do understand that this method is like scratching the left ear with the right heel? – Eugene Sh. Apr 20 '21 at 20:38
  • @EugeneSh. The customer is always right. – stark Apr 20 '21 at 20:42
  • @stark Yet a proper disclaimer should be stated :) – Eugene Sh. Apr 20 '21 at 20:45
  • yes i know, but my teacher wants this ) If you know any other methods,please,write – With Orxan Apr 20 '21 at 20:47
  • "i want square numbers as 1.2162e+5 and without loss of accuracy" and `exp(log(x)+log(x))` leads to precision loss versus the direct `x*y`. You have 2 goals in conflict. – chux - Reinstate Monica Apr 21 '21 at 04:22
  • @chux-ReinstateMonica `sqr` alone is losing precision as `x*x` needs twice the mantissa bits ... – Spektre Apr 21 '21 at 06:49
  • If [log/exp pow approach](https://stackoverflow.com/a/19072451/2521214) is not an option I would use binary long multiplication instead of repeated addition ... you know if you got to compute `sqr(10^50)` it would take a long time to compute with repeated addition... the binary version will be just `O(1)` with 24 or 53 iterations depending on if used `float` or `double` ... this might help [Bias value and range of the exponent of floating point](https://stackoverflow.com/a/65390554/2521214) with separating mantisa/exponent for the computations. – Spektre Apr 21 '21 at 06:55
  • Also see [Power by squaring for negative exponents](https://stackoverflow.com/a/30962495/2521214) for some ideas ... – Spektre Apr 21 '21 at 07:00
  • @Spektre If we were talking about integers, "sqr alone is losing precision as x*x needs twice the mantissa bits" makes some sense regarding absolute precision, but here, `x` is a FP. `x*x` incurs up to 0.5 ULP of _relative precision_ loss. `log(x)` and `exp()` each incur losses on the order of 1.0 ULP. Using `log2(x)` and `exp2()` would help a bit, yet an exponential approach is problematic when `x <= 0.0`. – chux - Reinstate Monica Apr 21 '21 at 09:28
  • With Orxan, in the end, code does `sqrt(sum)` and except for select values, will not meet "without loss of accuracy". Every `*, +=` step, unless we resort to some extended arithmetic type, incurs an accuracy loss. The goal "without loss of accuracy" in fundamentally unobtainable, even if code could used `*`. Please clarify realistic accuracy/precision goals. – chux - Reinstate Monica Apr 21 '21 at 09:37
  • @chux-ReinstateMonica yes I know the lossless computation of sqr is not achievable no matter what multiplication is used (that is what my comment was all about) btw. the doubling the mantissa bits is true also for non integer numbers. Also If you remember we both already dealt with [`(x<0)^(y)` problem](https://stackoverflow.com/a/67089172/2521214) just few days so `log,exp` approach is usable even then (but not as easily)... – Spektre Apr 21 '21 at 09:43
  • How can i solve problem , when i enter 2 numbers in program in description : 3.e165 and 4.e165 , why program print me 0? – With Orxan Apr 21 '21 at 09:50
  • you mean n=2 and then `3.e165 , 4.e165 ` ... I do not like this `if(a[i]<0){a[i]*=-1;}` better would be `if(a[i]<0.0) a[i]=-a[i];` back to the problem my bet is that `e165` is too big number once you `sqr` it overflows the `double` limit `~e308` ... as the result simply do not fit into double anymore as `165+165>308` ... – Spektre Apr 21 '21 at 10:10
  • And the fact that we then select the root does not play a role? – With Orxan Apr 21 '21 at 10:14
  • what root? you are squaring ... `(3.e165)^2 = 9.e+330` which is bigger than max representable double value (appart of `+inf`) so the result of your `exp2` is overflowing ... if you compute `3.e165*3.e165` directly it will also overflow ... – Spektre Apr 21 '21 at 10:15
  • yes, and how i can change program that this program work(without long double) – With Orxan Apr 21 '21 at 11:02
  • @WithOrxan by using bignum lib or by implementing such datatype yourself ... however usually minor change in computation can lead to usable number ranges ... so what exactly for you need this ? – Spektre Apr 21 '21 at 21:07

2 Answers2

0

Here is the method of squaring using repeated addition as suggested by @EmanuelP

int main(int argc, char ** argv)
{
    char *len;
    double f = strtod(argv[1],&len);
    char * pos = strchr(argv[1],'.');

    if (f <= 0.0 || pos == NULL) {
        printf("Invalid input. %p\n",pos);
        return -1;
    }
    int n = f;                 // integer part
    int frac = atoi(pos+1);    // fractional part
    printf("Int part %d, frac part %d\n",n,frac);
    /* Add integer times */
    double square = 0.0;
    while(n--)
        square += f;
    int i;
    for (i=0; i < (len -pos-1); i++)
        f /= 10.0;
    /* add fractional times */
    while (frac--)
        square += f;
    printf("%s %f\n",argv[1],square);
}
stark
  • 12,615
  • 3
  • 33
  • 50
0
#include <stdio.h>
#include <math.h>
#define N 10000
double norm2(double a[],int n);
int main(void)
{
    double a[N]; int n;
    scanf("%d",&n);
    
    printf("norm =%le",norm2(a,n));
    return 0;
}
double norm2(double a[],int n)
{
    int i=0; double sum=0,maxe,x;
    for(i=0;i<n;i++)
    scanf("%le",&a[i]);
    maxe=fabs(a[0]);
    for( i = 1; i < n; i++)
        if (maxe < fabs(a[i])) maxe = fabs(a[i]);
    for( i = 0; i < n; i++)
    {
        x = a[i]/maxe;
        sum += x*x;
    }
    return maxe*sqrt(sum);
    return 0;
    } 
With Orxan
  • 25
  • 6