To get better in programming C and to understand AI (machine learning) a little bit better, I wrote a tool in modern C to estimate a house price from a given house size. The code can be found on GitHub: jklingel/Simple-Linear-Regression: Calculate an estimated house price using simple linear regression (machine learning).
There is a lot of information on the internet about linear regressions, e.g. Linear Regression in 3 Minutes. In short: A training set of data is used to estimate a house price (output, y) from a given house size (input, x). Because we have only one independend variable, the size of the house, this is called a simple linear regression. Would we add i.e. the region, the county, the age, the house type, the builder etc. to the input, it would be called multiple linear regression.
My next exercise was to transfer the source code from my Linux development system over to a Commodore 64. Oh, what a pain! I got some help from Peculiarities of POWER C – Jan-Arendt Klingel, but overall this is no fun. Just the missing „{„, „}“, „<“ etc. are a pain in the neck. I found a work-around by replacing i.e. „{“ with „##“ in the original source code and then replacing „##“ in the POWER C editor back to „{„:
/##/{/<F3>
Let’s go through the source code block by block. First, necessary header files are included and the maximum number of training data is defined:
#include <stdio.h>
#include <math.h>
#define MAXVAL 50
The math library is needed for the square root function sqrt( ). Note that POWER C does not have a sqrtf( ) function for floating point values.
The following function calculates the standard deviation sigma „σ“ from values in an array, given the amount of values in n. MS Excel calls this function STABW.N and also follows the equation
σ = √(∑(xᵢ – μ)² / n)
float getSigma(val,n)
float val[MAXVAL];
int n;
{
int i;
float mu;
i=0;
mu=0.0;
while(i < n) {
mu += val[i];
i += 1;
}
mu /= n;
printf("Mean mu: %.2f\n", mu);
i=0;
while(i < n) {
val[i]=(val[i]-mu)*(val[i]-mu);
i++;
}
i=0;
float variance = 0.0;
while(i<n) {
variance += val[i];
i++;
}
variance /= n;
return(sqrt(variance));
}
The function works by calulating the mean mu („μ“) of all values, then the mean of each distance from each value to the mean („variance“). The standard deviation is the square root of the variance. My use of „i++“ versus „i+= 1“ is a little bit inconsistent here.
Next the code to calculate the Pearson correlation coefficient r:
float calculate_correlation(x,y,n)
float x[];
float y[];
int n;
{
float sum_X = 0, sum_Y = 0, sum_XY = 0;
float sum_X2 = 0, sum_Y2 = 0;
int i;
for (i = 0; i < n; i++) {
sum_X += x[i];
sum_Y += y[i];
sum_XY += x[i] * y[i];
sum_X2 += x[i] * x[i];
sum_Y2 += y[i] * y[i];
}
float numerator = (n * sum_XY) - (sum_X * sum_Y);
float denominator = sqrt((n * sum_X2 - (sum_X * sum_X)) * (n * sum_Y2 - (sum_Y * sum_Y)));
if (denominator == 0)
return(0.0);
return(numerator / denominator);
}
The Pearson correlation coefficient r tells us how strongly the x and the y values are related. For that, r is between -1 and 1. 0 means no correlation (like the correlation between my former school grates and the growth of trees). -1 is a strong negative correlation, 1 is a strong positive correlation. As the house size most likely has something to do with the house price, we expect a strong positive correlation. And indead, in this example r is 0.915249. The equation used is

The main function is
int main(void)
{
int i, n = 0;
float pprice = 0.0;
int squaref = 0;
float r,sx,sy,a,b = 0.0;
float xbar, ybar;
float price[MAXVAL];
price[0] = 316000.0;
price[1] = 277000.0;
price[2] = 155000.0;
price[3] = 253000.0;
price[4] = 211000.0;
price[5] = 329000.0;
price[6] = 317000.0;
price[7] = 360000.0;
price[8] = 204000.0;
price[9] = 250000.0;
price[10] = '\0';
float square[MAXVAL];
square[0] = 1852.0;
square[1] = 1975.0;
square[2] = 1176.0;
square[3] = 1550.0;
square[4] = 1458.0;
square[5] = 2689.0;
square[6] = 2259.0;
square[7] = 2763.0;
square[8] = 1325.0;
square[9] = 1992.0;
square[10] = '\0';
while(price[n] != '\0')
n++;
printf("Number of Elements n: %d\n", n);
xbar = 0.0;
for(i=0;i<n;i++)
xbar += square[i];
xbar /= n;
printf("xbar: %.1f\n", xbar);
ybar = 0.0;
for(i=0;i<n;i++)
ybar += price[i];
ybar /= n;
printf("ybar: %.1f\n", ybar);
r = calculate_correlation(square,price,n);
printf("r: %f\n", r);
sx = getSigma(square,n);
printf("Standard deviation sx: %.2f\n", sx);
sy = getSigma(price,n);
printf("Standard deviation sy: %.2f\n", sy);
b = r*sy/sx;
a = ybar-b*xbar;
printf("Coefficient a and b: %.2f, %.2f\n", a, b);
printf("Enter the square footage of the house: ");
scanf("%d", &squaref);
pprice = b*squaref+a;
printf("The estimated house price is: %.0f\n", pprice);
return(0);
}
The variable pprice is the estimated house price from a given house size in square feet called squaref. In this code, initalizing the test data price[ ] and square[ ] line by line is not very elegant.
If the test data would get initialized as integers as in „price[0] = 316000“, the compiler will complain with „*** integer constant too big“. Note that the largest value an unsigned integer in POWER C can hold is the 16-bit value 65.535. POWER C does not support larger integers, nor does it support the data types long and double!
If the values would get initialized as floating points as in „price[0] = 316000.0“ but xbar and ybar are still integers, the code produces the runtime error „*** illegal float quantity“ when calculating ybar. Ask me how I know…
The estimated house price pprice (x) is calculated by using the equation for the straight (linear) line that goes through all points {x,y} with the smallest distance between the points {x,y} and the line. The equation is y = bx + a, with y being the house size squaref.
The coefficient b is the slope of the line b = r * sy/sx, with s being the standard deviation sigma, first of all x values, then of all y values.
a describes the point where the line crosses through the y axis: a = ybar – b * xbar. ybar is the mean of all y values, xbar is the mean of all x values.
Terminating the test data manually with a ‚\0‘ is not an elegant solution. But so far I have not found a better solution to count the elements in the array. In GCC, „while(i != ‚\0‘)“ works just fine without planting the string-end sign manually.
The whole source code for the C64 can be found at Simple-Linear-Regression/slr.c at main · jklingel/Simple-Linear-Regression.
The C64 version of the C code has 111 lines of code and takes up 10 blocks (2.560 bytes) on the floppy disk. The compiled and linked version takes up 30 blocks (7.680 bytes). On a Linux computer the GCC compiler version 14.2.0 created a x86 binary file with 16.152 bytes! The POWER C object file can be further optimized with the „trim“ command:
$ trim slr.o
5131 bytes in
4955 bytes out
3.4% improvement
$
Not bad for our grandpa compiler from the 80s! Compiled without shell support („link -s“), the binary takes up 34 blocks (8.704 bytes).
One strange behaviour of the linker from POWER C is that the math header file math.h, the library math.l, and the compiled function sqrt.obj had to be on the work disk. The linker did not check the object disk for these files! If the sqrt.obj file is missing on the work disk, the linker is in an endles loop searching for it:
62, file not found, 00,00
62, file not found, 00,00
62, file not found, 00,00
The successfull linking stage looks like (slr.o is the compiled source code slr.c):
$ link
> slr.o
> math.l
> ↑
output file name: slr.sh
$