This question already has answers here:
Is floating point math broken?
(31 answers)
Closed last month.
First, my environment:
Distributor ID: Bunsenlabs
Description: BunsenLabs GNU/Linux 10.5 (Lithium)
Release: 10.5
Codename: buster
Thread model: posix
gcc version 8.3.0 (Debian 8.3.0-6)
I working on an old C program and ran into a rounding error in the program. I have copied the code into an the program "example.c" below:
main()
{
float acntBalance;
int dollars;
int cents;
float fcents;
dollars = 303466;
cents = 95;
fcents = cents * 0.01;
acntBalance = dollars + fcents;
printf("Dollars(%d) + Cents(%f) = %f \n",dollars,fcents,acntBalance);
}
and compiled this code using the GNU compiler as follows:
gcc -w -g -o example example.c
Adding 303466 dollars to 95 cents should be 303466.95,
but prints out as 303466.937500.
This is an accounting program and being 1 cent off is not acceptable.
This looks like a bug to me, but it has been so long since I worked on a C program, so I will say "user error" is the mostly like problem here. But this seems so basic, that I don't see where I am making an error.
If the error is not mine, is it H/W or S/W. I have run the program on 2 different hosts, so it leads me to believe it is a S/W error. But where?
Can anyone see an error in my code?
%.1f = one decimal place
%.2f = two decimal places
...
printf("Dollars(%d) + Cents(%f) = %.2f \n",dollars,fcents,acntBalance);
Related
I have two OS on my PC with i7-3770 # 3.40 GHz. One OS is latest Linux Kubuntu 18.04, the other OS is Windows 10 Pro running on same HDD.
I have tested a simple funny program written in C language doing some arithmetic calculations from number theory. On Kubuntu compiled with gcc 7.3.0, on Windows compiled with gcc 5.2.0. built by MinGW-W64 project.
The result is amazing, running program was 4-times slower on Linux, than on Windows.
On Windows the elapsed time is just 6 seconds. On Linux is elapsed time 24 seconds! On the same hardware.
I tried on Kubuntu to compile with some CPU specific options like "gcc -corei7" etc., but nothing helped. In the program is used "math.h" library, so the compilation is done with "-lm" on both systems. The source code is the same.
Is there a reason for this slow speed under Linux?
Further more I have compiled the same code also on older 32-bit machine with Core Duo T2250 # 1.73 GHz under Linux Mint 19 with gcc 7.3.0. The elapsed time was 28 seconds! Not much difference than 64-bit machine running on double frequency under Linux.
The sorce code is below, you can compile it and test it.
/* Program for playing with sigma(n) and tau(n) functions */
/* Compilation of code: "gcc name.c -o name -lm" */
#include <stdio.h>
#include <math.h>
#include <time.h>
int main(void)
{
double i, nq, x, zacatek, konec, p;
double odx, soucet, delitel, celkem, ZM;
unsigned long cas1, cas2;
i=(double)0; soucet=(double)0; celkem=(double)0; nq=(double)0;
zacatek=(double)1; konec=(double)1000000; x=zacatek;
ZM=(double)16 / (double)10;
printf("\n Program for playing with sigma(n) and tau(n) functions \n");
printf("---------------------------------------------------------\n");
printf("Calculation is running in range from %.0lf to %.0lf\n\n\n", zacatek, konec);
printf("Finding numbers which have sigma(n)/n = %.3lf\n\n", ZM);
cas1=time(NULL);
while (x <= konec) {
i=1; celkem=0; nq=0;
odx=sqrt(x)+1;
while (i <= odx) {
if (fmod(x, i)==0) {
nq++;
celkem=celkem+x/i+i;
}
i++;
}
nq=2*nq-1;
if ((odx-floor(odx))==0) {celkem=celkem-odx;}
if (fabs(celkem - (ZM*x)) < 0.001) {
printf("%.0lf has sum of all divisors = %.3lf times the number itself (%.0lf, %.0lf)\n", x, ZM, celkem, nq+1);
}
x++;
}
cas2=time(NULL);
printf("\n\nProgram ended.\n\n");
printf("Elapsed time %lu seconds.\n\n", cas2-cas1);
return (0);
}
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I hope someone can help me. I am working through CS50x and am working on Pset1 - greedy. I am getting the following error whenever I compile my code:
/tmp/greedy-46be96.o: In function `main':
greedy.c:(.text+0x95): undefined reference to `round'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any help will be greatly appreciated. I apologise if the question is vague, I have tried to be in depth. I have used man round in the terminal, and have searched everywhere, trying different solutions, but nothing has worked.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
float owed;
float change;
float quarter = 0.25;
float dime = 0.10;
float nickel = 0.05;
float penny = 0.01;
do {
printf("How much change is owed?: ");
owed = GetFloat();
} while(owed <= 0);
change = round(owed * 100);
}
I am using this command to compile my code:
clang -o greedy greedy.c -lcs50
The following should work when you compile:
clang -o greedy greedy.c -lcs50 -lm
This links the math library for the compiler.
I have an algorithm coded in MATLAB, which contains complex arc cos of some value (computation requires arccos of 15, which is approximately 3.4i). I want to code C or C++ counterpart of this code running on my Windows 7 PC. Actually, I want to produce it as a mex function compiled with Visual Studio C++.
I included "complex.h" and used cacosf function (complex arccos returning float _Complex) but I could not compile it as a mex function because Visual C++ compiler does not have "complex.h" support. However, mex file can take libraries as input, so I can compile my c code with another compiler that MATLAB does support (for example mingw, I integrated it to matlab with gnumex utility.) I downloaded Bloodshed C++ IDE which uses mingw at backend, I can compile my c++ code. The following C++ code represents a similar operation to my goal:
#include <stdio.h>
#include <complex.h>
int main() {
float _Complex myComplex;
myComplex = cacosf(5);
printf("Complex number result of acos(5) is : %f + %fi \r\n",crealf(myComplex),cimagf(myComplex));
return 0;
}
The output should be:
Complex number result of acos(5) is : 0.000000 + -2.292432i
However I get
Complex number result of acos(5) is : -1.#IND00, -0.000000
When I compile my C++ code with Linux GCC on Ubuntu 14.04 computer with Eclipse CDT Luna I get
The output should be:
Complex number result of acos(5) is : 0.000000 + -2.292432i
Where can I be wrong? Why can't I compile this code in Windows + mingw setup?
Note: I can compute cacosf(0) as 1.570796 + -0.000000 when I use mingw.
What version of mingwrt are you using? With mingwrt-3.21.1, the following works for me, (cross-compiling on a Linux host, and running under wine):
$ cat foo.c
#include <stdio.h>
#include <complex.h>
int main()
{
double _Complex Z = cacos(5.0);
printf( "arcos(5) = (%g, %gi)\n", __real__ Z, __imag__ Z );
return 0;
}
$ mingw32-gcc -o foo.exe foo.c
$ ./foo.exe
arcos(5) = (0, -2.29243i)
This seems to be consistent with your expected result. However, if you use any mingwrt version pre-dating mingwrt-3.21, (and the less said about utterly broken mingwrt-4.x the better), then there is a known bug resulting from arbitrarily deeming any purely real cacos() argument value greater than (1.0, 0.0i) to be outside the valid domain, (as would be the case for acos() on its real part), which would yield the result you report.
Visual C++, as the name says, is a C++ compiler. C++ uses the <complex> header and std::complex<float> type. Since C++ has overloading, you can call std::acos for complex values too.
Your code is in fact C, which is no longer supported by MSVC++. (They stopped doing that back in 1996 or so)
I'm learning the basics of SIMD so I was given a simple code snippet to see the principle at work with SSE and SSE2.
I recently installed minGW to compile C code in windows with gcc instead of using the visual studio compiler.
The objective of the example is to add two floats and then multiply by a third one.
The headers included are the following (which I guess are used to be able to use the SSE intrinsics):
#include <time.h>
#include <stdio.h>
#include <xmmintrin.h>
#include <pmmintrin.h>
#include <time.h>
#include <sys/time.h> // for timing
Then I have a function to check what time it is, to compare time between calculations:
double now(){
struct timeval t; double f_t;
gettimeofday(&t, NULL);
f_t = t.tv_usec; f_t = f_t/1000000.0; f_t +=t.tv_sec;
return f_t;
}
The function to do the calculation in the "scalar" sense is the following:
void run_scalar(){
unsigned int i;
for( i = 0; i < N; i++ ){
rs[i] = (a[i]+b[i])*c[i];
}
}
Here is the code for the sse2 function:
void run_sse2(){
unsigned int i;
__m128 *mm_a = (__m128 *)a;
__m128 *mm_b = (__m128 *)b;
__m128 *mm_c = (__m128 *)c;
__m128 *mm_r = (__m128 *)rv;
for( i = 0; i <N/4; i++)
mm_r[i] = _mm_mul_ps(_mm_add_ps(mm_a[i],mm_b[i]),mm_c[i]);
}
The vectors are defined the following way (N is the size of the vectors and it is defined elsewhere) and a function init() is called to initialize them:
float a[N] __attribute__((aligned(16)));
float b[N] __attribute__((aligned(16)));
float c[N] __attribute__((aligned(16)));
float rs[N] __attribute__((aligned(16)));
float rv[N] __attribute__((aligned(16)));
void init(){
unsigned int i;
for( i = 0; i < N; i++ ){
a[i] = (float)rand () / RAND_MAX / N;
b[i] = (float)rand () / RAND_MAX / N;
c[i] = (float)rand () / RAND_MAX / N;
}
}
Finally here is the main that calls the functions and prints the results and computing time.
int main(){
double t;
init();
t = now();
run_scalar();
t = now()-t;
printf("S = %10.9f Temps du code scalaire : %f seconde(s)\n",1e5*sum(rs),t);
t = now();
run_sse2();
t = now()-t;
printf("S = %10.9f Temps du code vectoriel 2: %f seconde(s)\n",1e5*sum(rv),t);
}
For sum reason if I compile this code with a command line of "gcc -o vec vectorial.c -msse -msse2 -msse3" or "mingw32-gcc -o vec vectorial.c -msse -msse2 -msse3"" it compiles without any problems, but for some reason I can't run it in my windows machine, in the command prompt I get an "access denied" and a big message appears on the screen saying "This app can't run on your PC, to find a version for your PC, check with the software publisher".
I don't really understand what is going on, neither do I have much experience with MinGW or C (just an introductory course to C++ done on Linux machines). I've tried playing around with different headers because I thought maybe I was targeting a different processor than the one on my PC but couldn't solve the issue. Most of the info I found was confusing.
Can someone help me understand what is going on? Is it a problem in the minGW configuration that is compiling in targeting a Linux platform? Is it something in the code that doesn't have the equivalent in windows?
I'm trying to run it on a 64 bit Windows 8.1 pc
Edit: Tried the configuration suggested in the site linked below. The output remains the same.
If I try to run through MSYS I get a "Bad File number"
If I try to run throught the command prompt I get Access is Denied.
I'm guessing there's some sort of bug arising from permissions. Tried turning off the antivirus and User Account control but still no luck.
Any ideas?
There is nothing wrong with your code, besides, you did not provide the definition of sum() or N which is, however, not a problem. The switches -msse -msse2 appear to be not required.
I was able to compile and run your code on Linux (Ubuntu x86_64, compiled with gcc 4.8.2 and 4.6.3, on Atom D2700 and AMD Athlon LE-1640) and Windows7/64 (compiled with gcc 4.5.3 (32bit) and 4.8.2 (64bit), on Core i3-4330 and Core i7-4960X). It was running without problem.
Are you sure your CPU supports the required instructions? What exactly was the error code you got? Which MinGW configuration did you use? Out of curiosity, I used the one available at http://win-builds.org/download.html which was very straight-forward.
However, using the optimization flag -O3 created the best result -- with the scalar loop! Also useful are -m64 -mtune=native -s.
Yes, it's been asked before, but every answer I come up with on SO and elsewhere has to do with compiling C++ code in gcc instead of g++, or a issue of some kind with standard libraries. So far, nothing actually lining up right for me here.
So, I'm going through a basic crash course on C, and trying to compile an example used to illustrate linking to files that you create, rather than from the standard libraries. Here's the code:
math_functions.h
int sum (int x, int y);
float average (float x, float y, float z);
math_functions.c
int sum (int x, int y)
{
return (x + y);
}
float average (float x, float y, float z)
{
return (x + y + z) / 3;
}
and finally
test3.c
#include <stdio.h>
#include "math_functions.h"
main ()
{
int theSum = sum (8, 12);
float theAverage = average (16.9, 7.86, 3.4);
printf ("the sum is: %i ", theSum);
printf ("and the average is: %f \n", theAverage);
printf ("average casted to an int is: %i \n", (int)theAverage);
}
These are all in the same folder. When I open the Terminal, cd to the folder and run:
gcc test3.c -o test3
I get:
Undefined symbols for architecture x86_64:
"_average", referenced from:
_main in ccmf69Tt.o
"_sum", referenced from:
_main in ccxms0fF.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
This happens if I use gcc or g++ (which I shouldn't have to do, since this should all be C), and everything I've compiled before now works fine with the
#include <stdio.h>
at the top.
I can get it to compile and run fine by removing the
#include "math_functions.h"
from the test3.c file, putting the contents of math_functions.h before main() and the contents of math_functions.c after main(). And yes, that is copy and paste, so its definitely the same code.
So yeah, I can get my code to work, but it defeats the purpose of the exercise, in that I don't end up being able to use that code in any other C files without copying it and pasting it into the one file...
So I'm wondering, is there a way I can fix this, so I can include more that just the standard C, C++ and Objective-C libraries?
This happens through box the Terminal, manually typing out the gcc command, and through CodeRunner, which has the standard commands all tucked away into a button, so I can't stuff it.
I'm running Mountain Lion 10.8.4 (12E55) on a 2012 Mac Mini, using the Command Line Tools from Xcode 4.6.2 (installed them just a few hours ago, I haven't actually done much then standard use of the Mini till now)
I have all the same software installed on my MacBook Air, but haven't tested it to see if the same goes down yet.
Any pointers? If someone else has had this and worked it out somewhere here on SO, please point me at it, I have been looking for round an hour but like I said before, all the solutions that I've found so far end up being when there is C++ code or something weird with the standard libraries.
You just need to compile the maths_function. The linker is complaining it does not have the definitions contained in that module.
gcc test3.c math_functions.c -o test3