• Welcome to the new Internet Infidels Discussion Board, formerly Talk Freethought.

The Programming Thread

I'm going through a training program at work related to data science, and next up is functional programming in Python.

I'm pretty good at Python, and I've used some FP patterns in various languages, but I figured the best way to understand this different paradigm is to use a language that's designed for it. So I'm learning Haskell:



Turns out I'd only barely scratched the surface of FP in my previous work. I had used some of these patterns before but there was almost always imperative logic mixed in there.

It's a bit like trying to learn a new set of tools, while constantly reaching for the old set of familiar tools that are not there.
 
An alternative to object-oriented programming is functional programming, and some people *love* it. But I find that it has its limitations, because most functional programming treats data objects as immutable, when one wants mutability for large sets of data where one wants to change only some of that set's contents without copying the entire set.
The copy and the original share most of the same data in memory, using persistent data structures.

So for example, you might implement a list as a tree, and each node in the tree points to a few other nodes, and the leaves of the tree are the element in the list. If you have a massive list and you make a copy of that list but only change one element, then the new list will contain almost all of the same nodes as the old list, except for the nodes that are ancestors of the new element. So if you copy a list with a million items in it you may only need to actually add a handful of new elements in memory.
 
All I used ws C.C++, Haskel looks C like.

The principles of functionalstructured programing are as I applied it are

1. Break a program don into small testable functions.
2. Top down execution with no jumps or goto statements. Opposite of spaghetti code.
3. Self doubting code, use meaningful variable and function names.
4. Limit number of nested function calls.
5. Single exit points from functions

The idea is to make the code easy to follow, debug, and maintain.

When code gets into the thousands of lines you can see the utility.

In general braking code into functions makes software design easier for the coder. In the days of random spaghetti code one would sit down and write code off the top of the head leading to a mess.

Before codn,g on paper pesudo code the problm and work out the functions you need to make it work. Write ad test functions, and integrate. It gets more complicated but that is it, at least for me.

void main(){

int a,b,c.

a = function_that_does_this(b);
.
.
lines of code
.
.
c = funcnction_that does_that(a);

}
 
Looking at that discussion, it's evident that C is relatively low-level, because its built-in object references are very low-level: pointers. It's easy to lose track of allocated resources for them.

C++ was built on top of C, and many of its features are type-safe and memory-safe alternatives to using the C preprocessor. For instance, as alternatives to malloc() and free(), it has type-safe "new" and delete.

The C++ Standard Template Library includes several container classes, and they do all their allocation and deallocation inside themselves. The STL also includes "smart pointers" that deallocate the pointed-to memory block when they go out of scope. Its container classes can be interpreted as smart array pointers.

Const declarations and templates are type-safe alternatives to using the preprocessor. Recent versions of C++ have introduced features that make it more like higher-level languages like Python, like anonymous functions and automatic typing with the "auto" keyword. A recently-introduced feature is "concepts", constraints on types for templates, like that a type must support comparison operations or that it must be an integer type.
 
Looking at that discussion, it's evident that C is relatively low-level, because its built-in object references are very low-level: pointers. It's easy to lose track of allocated resources for them.

C++ was built on top of C, and many of its features are type-safe and memory-safe alternatives to using the C preprocessor. For instance, as alternatives to malloc() and free(), it has type-safe "new" and delete.

The C++ Standard Template Library includes several container classes, and they do all their allocation and deallocation inside themselves. The STL also includes "smart pointers" that deallocate the pointed-to memory block when they go out of scope. Its container classes can be interpreted as smart array pointers.

Const declarations and templates are type-safe alternatives to using the preprocessor. Recent versions of C++ have introduced features that make it more like higher-level languages like Python, like anonymous functions and automatic typing with the "auto" keyword. A recently-introduced feature is "concepts", constraints on types for templates, like that a type must support comparison operations or that it must be an integer type.
To be fair, all that guff involving counting and cleaning up for the programmer itself has a cost.

Forcing the programmer to learn how to account for object life cycles has a huge benefit in the form of really fast code, assuming it is programmed slowly and carefully.

Managed languages are a lot worse in terms of speed, because the framework is constantly being called to clean up your room like a maid... instead of "you always having access to your always-clean room because you clean up at well defined times, and have well ordered uses for that space" you have "you get kicked out of your room unceremoniously so the maid can clean for you".

You also lose access to a number of platforms that don't have the space for larger libraries.

All in all, managed languages are nice but they are also problematic for any kind of programming that needs to be fast.

It's nice having such a "high level" low level language.
 
All I used ws C.C++, Haskel looks C like.
It's very different.

Give it a try. I'm enjoying learning a new paradigm - you might, too.
next up is functional programming in Python.
Turns out this was a total fizzer. The course basically just introduced functools, currying and list comprehensions. DIdn't even answer the big question in my mind, which is, "how do you want me to handle side effects?"
 
In the 80s the idea was C would be a universal portable cross platform language. Keep applcation code separate from local platform system utilities to ease porting.

C allowed me to write low level IO drivers for boards on the old AT bus. These days it would be a USB driver.

It depends on what you are doing. C followed by C++ was suited for the math work I had to do for work. Simulations and analysis.

And embedded software.

There are international ISO and ANSI standards for C/C++. Don't know about other languages.

If you are dong serious work that gets uruted you have to pay attnction to future support.

If I were doing serious deliverable software I'd get an MS Visual Studio license.

So much for a walk down memory lane.
 
Roulette

Roulette brought up on a math thread.

Get out your monopoly money and see if you can up with a scheme to beat the house. I never played roulette, but you can look up Vegas rules on the net.


One function tests the Scilab random number generator. It is not an exact uniform distribution, but I doubt the roulette wheel is perfect either.

The game function generates a random number from 1-38 slots and returns a string of the slot number and color. G green, r red, b black.

Easily ported to any language that can generate random integers within a range.


Scilab uniform random distribution. The ideal count is 10,000 per number. The numbers will change on successive runs.

Code:
g 0       9998
b02        9987
r14        9897
b35        9993
r23       10157
b04        9852
r16        9845
b33        9908
r21        9866
b06       10162
r18       10021
b31       10059
r19       10180
b08       10089
r12       10093
b29       10140
r25        9944
b10       10008
r27        9999
g00       10077
r01        9974
b13       10057
r36       10051
b24       10034
r03       10013
b15       10000
r34        9844
b22       10032
e05       10038
b17       10023
r32        9959
b20        9833
r07       10025
b11        9871
r30       10247
b26        9858
r09        9955
b28        9911


Code:
clear
clc
nslots = 38
ntrials = nslots*10000

slots = ["g  0", "b02", "r14","b35", "r23", "b04" ,"r16" ,"b33" ,"r21",...
"b06", "r18", "b31","r19", "b08", "r12", "b29" ,"r25" ,"b10" ,"r27", ...
"g00", "r01" ,"b13", "r36", "b24", "r03" ,"b15" ,"r34" ,"b22", ...
"e05", "b17", "r32", "b20", "r07", "b11", "r30", "b26","r09", "b28"]

function check_distribution(ntrials,nslots,slots)
    //check the random numer generator
    //for n trails counts the occurences of numbers 1-38
    y = grand(1,ntrials,"uin",1,nslots)
    bin_count = zeros(1,nslots)
    for i=1:ntrials
        bin_count(y(i)) = bin_count(y(i)) + 1
    end
    mprintf("%3s  %10d\n",slots',bin_count')
endfunction


function [slot] = spin_the_wheel(nslots,slots)
    y = grand(1,1,"uin",1,nslots)
    slot = slots(y)
endfunction

check_distribution(ntrials,nslots,slots)

[slot] = spin_the_wheel(nslots,slots)
disp(slot)
 
A rough comparison of decimal places for size of the integer parts for floats, doubles, and long doubles.

The floating point standard


Code:
int save(float *x,double *y, long double *z) {
    int i;
    FILE *p = fopen("nums.txt","w");
    if(!p){
        cout<<"file error"<<endl;
        return 1;
       }
    for(i=0;i<18;i++)fprintf(p,"%40.20f\n",x[i]);
    for(i=0;i<18;i++)fprintf(p,"%40.20f\n",y[i]);
    for(i=0;i<18;i++)fprintf(p,"%40.20Lf\n",z[i]);
    fclose(p);
    cout << "SAVE DONE" << "\n";
    return 0;
}//save()

int main(){
    int i,s;
    float xfa[18],xf = 0.01234567890123456789;
    long double xlda[18],xld = 0.01234567890123456789;
    double xda[18],xd = 0.01234567890123456789;
    for(i=0;i<18;i++){
        xfa[i] = xf;
        xda[i] = xd;
        xlda[i] = xld;
        xf += 9*pow(10,i);
        xd += 9*pow(10,i);
        xld += 9*pow(10,i);
        }
    save(xfa,xda,xlda);

    return 0;
}

Code:
float
                  0.01234567910432815552
                  9.01234531402587890625
                 99.01234436035156250000
                999.01232910156250000000
               9999.01269531250000000000
              99999.01562500000000000000
             999999.00000000000000000000
            9999999.00000000000000000000
          100000000.00000000000000000000
         1000000000.00000000000000000000
        10000000000.00000000000000000000
        99999997952.00000000000000000000
       999999995904.00000000000000000000
      9999999827968.00000000000000000000
    100000000376832.00000000000000000000
    999999986991104.00000000000000000000
  10000000272564224.00000000000000000000
  99999998430674944.00000000000000000000

double
                  0.01234567890123456843
                  9.01234567890123372536
                 99.01234567890122661993
                999.01234567890128346335
               9999.01234567890060134232
              99999.01234567890060134232
             999999.01234567887149751186
            9999999.01234567910432815552
           99999999.01234567165374755859
          999999999.01234567165374755859
         9999999999.01234626770019531250
        99999999999.01234436035156250000
       999999999999.01232910156250000000
      9999999999999.01171875000000000000
     99999999999999.01562500000000000000
    999999999999999.00000000000000000000
  10000000000000000.00000000000000000000
 100000000000000000.00000000000000000000

long double
                  0.01234567890123456843
                  9.01234567890123456843
                 99.01234567890123457190
                999.01234567890123455802
               9999.01234567890123461353
              99999.01234567890123372536
             999999.01234567890122661993
            9999999.01234567890151083702
           99999999.01234567890060134232
          999999999.01234567887149751186
         9999999999.01234567910432815552
        99999999999.01234567910432815552
       999999999999.01234567165374755859
      9999999999999.01234531402587890625
     99999999999999.01234436035156250000
    999999999999999.01232910156250000000
   9999999999999999.01269531250000000000
  99999999999999999.01562500000000000000
 
Having a function to save numerical arrays of any number is handy, without having to modify a function function for the number of arrays.

It was easy to do in Python.

In C I tried to use the variable arguments function and could not figure out how how to pass a pointer to an array through the argument list.

Could not pass a pointer through to n. Tried all combinations I could think of. Net info sayss it should be possible, maybe not.

Code:
void varg_ptr(char *fmt,...){
    va_list args;
    va_start(args, fmt);

     while (*fmt != '\0') {

        if(*fmt == 'd') {
            //n = va_arg(args, int);
            int *n = va_arg(args, int);
            cout<<n<<endl;
        }//if
     ++fmt;
     }//while
    va_end(args);;
   
    int main()
{
     
    int z = 123;
    int *pi = &z;
    varg_ptr("%d",pi);
    return 0;;
}  
   
}



This works.

Pass an array of void pointers pointing to arrays. Format string says how to cast each array as int or double. Print/write one row at a time across each array.


Code:
int  varrf(char *fn,int nrows,char *s,void *p[]){
    int col,row;
    int ncols = strlen(s);
    //check for format errors
    for(col=0;col<ncols;col++)
        if(s[col] != 'd' && s[col] !='f')return 1;

   FILE *f = fopen(fn,"w");
    for(row=0;row<nrows;row++){
        for(col=0;col<ncols;col++){
            switch (s[col]){
                case 'd':
                printf("%d  ",*(int*)p[col] + row);
                fprintf(f,"%d  ",*(int*)p[col] + row);
                break;
                case 'f':
                printf("%f  ",*(double*)p[col] + row);
                fprintf(f,"%f  ",*(double*)p[col] + row);
                break;
            }
        }
        printf("\n");
        fprintf(f,"\n");
    }
    fclose(f);
    return 0;
   
    int main()
{
    char *fmt = "df", *fn = "data.txt";
    int i,n=5,x[n],err;
    void *p[2];
    double y[n];
    for(i=0;i<n;i++){x[i] = i;y[i] = i + 1;}
    p[0] = x;
    p[1] = y;
    err = varrf(fn,n,fmt,p);
    if(err)cout<<"error";
 
    return 0;;
}

File data

0  1.000000 
1  2.000000 
2  3.000000 
3  4.000000 
4  5.000000
 
What is this damn utf4mb3 character encoding you're trying to foist on me?? I didn't know it even existed in the wild these days, let alone on a new installation!
 
On the Python thread Barbos argued that logarithms can not be done on a computer and challenged me to show otherwise.

After a short review the net this is what I came up with.

I broke it into two sections. The first section computes ln for x > 0 and < 1. It uses power functions so it overflows as x gets large.

For x > 1 a brute force integration. It woks but as x gets large the integration gets worse because of granularity. Another technique or a better integration would be needed.

I don't know how the C library function log() works.

So this is what mathematicians do,nice work if you can get it.

Code:
double _log(double x){
    if(x == 1) return 0;
    if(x <= 0) return NAN;
    int n1 = 50;
    int n2 = int(1e6);
    int i,k;
    double lnx = 0.,y,dy;

    if(x < 1){
        for(k=1;k<n1;k++)
            lnx += pow(-1,k+1)*pow(x-1,k)/k;
        return lnx;
        }

    dy = (x-1.)/(n2-1);
    y = 1.;
    for(i=0;i<n2;i++){
        lnx += dy/y;
        y += dy;
    }
    return lnx;

}//log()



int main()
{
    double x,lne,lnc,d;
    int i;
    x = 123;
    lne = log(x);
    lnc = _log(x);
    d = lne - lnc;
    //printf("%.8f   %.8f   %.8f\n",lne,lnc,d);
   FILE *p = fopen("data.txt","w");
   for(i=1;i<=10;i++){
        lne = log(i/10.);
        lnc = _log(i/10.);
        d = lne - lnc;
        printf("%.8f   %.8f   %.8f\n",lne,lnc,d);
        fprintf(p,"%.15f   %.15f   %.15f\n",lne,lnc,d);
    }
    for(i=1;i<=100;i++){
        lne = log(i);
        lnc = _log(i);
        d = lne - lnc;
        printf("%.8f   %.8f   %.8f\n",lne,lnc,d);
        fprintf(p,"%.15f   %.15f   %.15f\n",lne,lnc,d);
    }
    fclose(p);
    return 0;
}



Code:
c log(), _log(), difference
x .1 to 1
-2.302585092994045   -2.301693176996925   -0.000891915997120
-1.609437912434100   -1.609436582947443   -0.000001329486657
-1.203972804325936   -1.203972803177448   -0.000000001148488
-0.916290731874155   -0.916290731873762   -0.000000000000393
-0.693147180559945   -0.693147180559945   -0.000000000000000
-0.510825623765991   -0.510825623765991   0.000000000000000
-0.356674943938732   -0.356674943938732   -0.000000000000000
-0.223143551314210   -0.223143551314210   0.000000000000000
-0.105360515657826   -0.105360515657826   0.000000000000000
0.000000000000000   0.000000000000000   0.000000000000000
x 1 to 100
0.000000000000000   0.000000000000000   0.000000000000000
0.693147180559945   0.693147930559666   -0.000000749999721
1.098612288668110   1.098613622000629   -0.000001333332520
1.386294361119891   1.386296236133235   -0.000001875013344
1.609437912434100   1.609440312433279   -0.000002399999179
1.791759469228055   1.791762385907071   -0.000002916679016
1.945910149055313   1.945913577636628   -0.000003428581315
2.079441541679836   2.079445479201067   -0.000003937521232
2.197224577336220   2.197229021783010   -0.000004444446790
2.302585092994046   2.302590043004541   -0.000004950010495
2.397895272798371   2.397900727361841   -0.000005454563470
2.484906649788000   2.484912608147924   -0.000005958359923
2.564949357461537   2.564955819016499   -0.000006461554963
2.639057329615258   2.639064293912869   -0.000006964297610
2.708050201102210   2.708057667801196   -0.000007466698986
2.772588722239781   2.772596691012312   -0.000007968772531
2.833213344056216   2.833221814663426   -0.000008470607210
2.890371757896165   2.890380730151967   -0.000008972255803
2.944438979166440   2.944448452882022   -0.000009473715581
2.995732273553991   2.995742248596676   -0.000009975042685
3.044522437723423   3.044532913965347   -0.000010476241924
3.091042453358316   3.091053430670683   -0.000010977312367
3.135494215929150   3.135505694254564   -0.000011478325415
3.178053830347946   3.178065809568318   -0.000011979220372
3.218875824868201   3.218888304928355   -0.000012480060155
3.258096538021482   3.258109518855262   -0.000012980833780
3.295836866004329   3.295850347548420   -0.000013481544091
3.332204510175204   3.332218492398993   -0.000013982223789
3.367295829986474   3.367310312834391   -0.000014482847917
3.401197381662155   3.401212365077845   -0.000014983415690
3.433987204485146   3.434002688444634   -0.000015483959487
3.465735902799727   3.465751887256522   -0.000015984456795
3.496507561466480   3.496524046406852   -0.000016484940371
3.526360524616162   3.526377510022207   -0.000016985406046
3.555348061489414   3.555365547318050   -0.000017485828636
3.583518938456110   3.583536924676787   -0.000017986220677
3.610917912644224   3.610936399252365   -0.000018486608140
3.637586159726386   3.637605146687660   -0.000018986961274
3.663561646129646   3.663581133451908   -0.000019487322262
3.688879454113936   3.688899441754728   -0.000019987640792
3.713572066704308   3.713592554670704   -0.000020487966396
3.737669618283368   3.737690606539606   -0.000020988256238
3.761200115693562   3.761221604225831   -0.000021488532269
3.784189633918261   3.784211622729199   -0.000021988810938
3.806662489770320   3.806684978855063   -0.000022489084744
3.828641396489095   3.828664385821917   -0.000022989332822
3.850147601710058   3.850171091268770   -0.000023489558712
3.871201010907891   3.871225000703891   -0.000023989796000
3.891820298110626   3.891844788121694   -0.000024490011068
3.912023005428146   3.912047995658363   -0.000024990230217
3.931825632724326   3.931851123153097   -0.000025490428771
3.951243718581428   3.951269709214904   -0.000025990633477
3.970291913552122   3.970318404362180   -0.000026490810058
3.988984046564275   3.989011037557636   -0.000026990993362
4.007333185232471   4.007360676416953   -0.000027491184482
4.025351690735150   4.025379682099570   -0.000027991364420
4.043051267834550   4.043079759360578   -0.000028491526027
4.060443010546419   4.060472002225126   -0.000028991678707
4.077537443905720   4.077566935736545   -0.000029491830825
4.094344562222100   4.094374554212496   -0.000029991990395
4.110873864173311   4.110904356306158   -0.000030492132847
4.127134385045092   4.127165377321226   -0.000030992276135
4.143134726391533   4.143166218793683   -0.000031492402150
4.158883083359671   4.158915075904764   -0.000031992545092
4.174387269895637   4.174419762568498   -0.000032492672861
4.189654742026425   4.189687734843567   -0.000032992817142
4.204692619390966   4.204726112329410   -0.000033492938444
4.219507705176107   4.219541698243686   -0.000033993067579
4.234106504597260   4.234140997772011   -0.000034493174751
4.248495242049359   4.248530235340529   -0.000034993291170
4.262679877041315   4.262715370432973   -0.000035493391658
4.276666119016055   4.276702112524914   -0.000035993508859
4.290459441148391   4.290495934763084   -0.000036493614693
4.304065093204170   4.304102086915726   -0.000036993711555
4.317488113536310   4.317525607349631   -0.000037493813321
4.330733340286331   4.330771334207156   -0.000037993920825
4.343805421853684   4.343843915883403   -0.000038494029718
4.356708826689592   4.356747820819210   -0.000038994129619
4.369447852467021   4.369487346678530   -0.000039494211508
4.382026634673881   4.382066628991367   -0.000039994317485
4.394449154672439   4.394489649081028   -0.000040494408589
4.406719247264253   4.406760241749455   -0.000040994485202
4.418840607796598   4.418882102374193   -0.000041494577594
4.430816798843313   4.430858793508214   -0.000041994664900
4.442651256490317   4.442693751230102   -0.000042494739786
4.454347296253507   4.454390291078563   -0.000042994825056
4.465908118654584   4.465951613565630   -0.000043494911046
4.477336814478207   4.477380809476868   -0.000043994998661
4.488636369732140   4.488680864815749   -0.000044495083610
4.499809670330265   4.499854665477776   -0.000044995147511
4.510859506516850   4.510905001752964   -0.000045495236114
4.521788577049040   4.521834572355258   -0.000045995306217
4.532599493153256   4.532645988525414   -0.000046495372158
4.543294782270004   4.543341777708954   -0.000046995438950
4.553876891600541   4.553924387124811   -0.000047495524270
4.564348191467836   4.564396187049426   -0.000047995581590
4.574710978503383   4.574759474163056   -0.000048495659673
4.584967478670572   4.585016474404523   -0.000048995733951
4.595119850134590   4.595169345938178   -0.000049495803588
4.605170185988092   4.605220181866348   -0.000049995878256
 
The first software class I took was FORTRAN in the 70s. Back when you had to punch cards for each line and have somebody run it on a computer in a computer center.

Never used it.

Another was ALGOL.


ALGOL (/ˈælɡɒl, -ɡɔːl/; short for "Algorithmic Language")[1] is a family of imperative computer programming languages originally developed in 1958. ALGOL heavily influenced many other languages and was the standard method for algorithm description used by the Association for Computing Machinery (ACM) in textbooks and academic sources for more than thirty years.[2]

In the sense that the syntax of most modern languages is "Algol-like",[3] it was arguably more influential than three other high-level programming languages among which it was roughly contemporary: FORTRAN, Lisp, and COBOL.[4] It was designed to avoid some of the perceived problems with FORTRAN and eventually gave rise to many other programming languages, including PL/I, Simula, BCPL, B, Pascal, and C.

ALGOL introduced code blocks and the begin...end pairs for delimiting them. It was also the first language implementing nested function definitions with lexical scope. Moreover, it was the first programming language which gave detailed attention to formal language definition and through the Algol 60 Report introduced Backus–Naur form, a principal formal grammar notation for language design.


Code:
procedure Absmax(a) Size:(n, m) Result:(y) Subscripts:(i, k);
    value n, m; array a; integer n, m, i, k; real y;
comment The absolute greatest element of the matrix a, of size n by m,
    is copied to y, and the subscripts of this element to i and k;
begin
    integer p, q;
    y := 0; i := k := 1;
    for p := 1 step 1 until n do
        for q := 1 step 1 until m do
            if abs(a[p, q]) > y then
                begin y := abs(a[p, q]);
                    i := p; k := q
                end
end Absmax



The problem with natural log is 1/x has no definite integral. There may be a series approximation instead of numerical integration.
 
It does have a definite integral, if one goes from one positive number to another. Definite integrals don't have to start at 0.
 
integral x^a dx = x^a+1/(a+1)
integral x^2 =( x^3)/3
integral x^-1 = ( x^(-1+1))/(-1+1) = (x^0)/0 = 1/0

You end up with divide by zero.
 
One must be more careful and do a definite integral. Let us do one for power a for x from x1 to x2:

\( \displaystyle{ \int_{x_1}^{x_2} x^a \, dx = \frac{(x_2)^{a+1} - (x_1)^{a+1}}{a+1} } \)

For a != -1, one can use the familiar indefinite integral to evaluate this definite integral:

\( \displaystyle{ \int x^a \, dx = \frac{x^{a+1}}{a+1} } \)

Strictly speaking, that is two indefinite integrals. For a > -1:

\( \displaystyle{ \int_0^x x^a \, dx = \frac{x^{a+1}}{a+1} } \)

For a < -1:

\( \displaystyle{ - \int_x^\infty x^a \, dx = \frac{x^{a+1}}{a+1} } \)

Back to that definite integral. Evaluating it at -1 gives us

\( \displaystyle{ \frac{1 - 1}{-1 + 1} = \frac{0}{0} } \)

An indefinite result.
 
Ok. I concede the point.

Changing from rectangular to trapezoidal interaction made an improvement.

Code:
double _log(double x){
    if(x == 1) return 0;
    if(x <= 0) return NAN;
    int n1 = 80;
    int n2 = int(1e6);
    int i,k;
    double lnx = 0.,dt,t;
    double y1 = 1.,y2,t2,t1=1;
    if(x < 1){
        for(k=1;k<n1;k++)
            lnx += pow(-1,k+1)*pow(x-1,k)/k;
        return lnx;
        }

    dt= (x-1.)/(n2-1);
    for(i=1;i<n2;i++){
        t2 = t1 + dt;
        y2 = 1./t2;
        y1 = 1./t1;
        lnx += dt*(y1 + ((y2 - y1)*0.5)  );
        t1 = t2;
    }
    return lnx;
 
For x > 1 a brute force integration. It woks but as x gets large the integration gets worse because of granularity. Another technique or a better integration would be needed.
[removed] log(x)=-log(1/x) hence: log(123)=-log(1/123)
That would help you to get rid of stupid integration. You're welcome.
That's not to say that code will be good, it would still be utter garbage, but at least you don't have to wait an hour to calculate log(123).
I don't know how the C library function log() works.
[removed]
 
Last edited by a moderator:
Back
Top Bottom