English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 03 July 2022, 09:51   #1
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
Why pow() is giving me this result?

(using vbcc in case this might be important for the question).

I am trying to calculate the "power of" and print it on screen. However for some reason I get a different result if I print the result of the pow() directly or store the result of pow() in double variable and print the variable value. Here is the code:
Code:
double base, power, result;
base = 2; power = 2;
result = pow(base,power);
printf("a: %.2lf b: %.2lf\n", result, pow(base,power));
The above code prints the following in the console:
Code:
a: 11-5./0400.00 b:4.01
I cannot understand why the results of a: and b: are different, they are the same pow() calculation with the only difference that a: shows the result which has been previously stored in a variable, and b: shows the result directly. The other thing I cannot understand is why the result of b: is 4.01 and not 4.0.

In order to compile the solution I added the -lmieee flag.

Would anyone know what is happening?

When I try the same code using an online C compiler I get the expected result (a: 4.00 b: 4.00).
Sim085 is offline  
Old 03 July 2022, 10:14   #2
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
You are using %lf in printf, try with %f

See for example this https://stackoverflow.com/a/4264154/8390560
alkis is offline  
Old 03 July 2022, 10:24   #3
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
Quote:
a: 11-5./0400.00
what is this output?

Check how pow is defined in your case. Is it returning a "float" or a "double"? if it returns a float, it's not going to end well with printf as %lf format is double (assigning in a double before hand solves the issue)
jotd is offline  
Old 03 July 2022, 10:28   #4
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
Thank you alkis, doing this gives the following result:
Code:
a: 1074790400.00 b: 4.00
This resolved the 4.01 / 4.00 issue.

So this leaves only the question on why storing the pow() result in a variable of type double prints something completely different than printing the result of pow() directly?

Quote:
Originally Posted by alkis View Post
You are using %lf in printf, try with %f

See for example this https://stackoverflow.com/a/4264154/8390560
Sim085 is offline  
Old 03 July 2022, 10:37   #5
thomas
Registered User
 
thomas's Avatar
 
Join Date: Jan 2002
Location: Germany
Posts: 6,985
Did you #include <math.h>?

All those float/double functions only work correctly with proper prototypes. By default all parameters and results of functions are expected to be int and the compiler converts to/from float where it should not. It's even worse with double. The compiler converts to int and pushes 32 bits to the stack where the function expects a 64bit double. Only with prototyped functions the compiler knows what to do.
thomas is offline  
Old 03 July 2022, 10:37   #6
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
I changed the code to float but still get same result:

Code:
float base, power, result;
base = 2; power = 2;
result = pow(base,power);
printf("a: %.2f b: %.2f\n", result, pow(base,power));
But this still gives the following result:

Code:
a: 1074790400.00 b: 4.00
When I check pow definition on the internet it takes two double parameters and returns a double which is why I was using double.

Quote:
Originally Posted by jotd View Post
what is this output?

Check how pow is defined in your case. Is it returning a "float" or a "double"? if it returns a float, it's not going to end well with printf as %lf format is double (assigning in a double before hand solves the issue)
Sim085 is offline  
Old 03 July 2022, 10:42   #7
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
I missed that!

Confirm that using either double or float is giving correct result when I add the #include <math.h>.

Quote:
Originally Posted by thomas View Post
Did you #include <math.h>?

All those float/double functions only work correctly with proper prototypes. By default all parameters and results of functions are expected to be int and the compiler converts to/from float where it should not. It's even worse with double. The compiler converts to int and pushes 32 bits to the stack where the function expects a 64bit double. Only with prototyped functions the compiler knows what to do.
Sim085 is offline  
Old 03 July 2022, 10:43   #8
bebbo
bye
 
Join Date: Jun 2016
Location: Some / Where
Posts: 680
well, it should print

a: 4.00 b: 4.00

even without any includes. That should only cause warnings...
bebbo is offline  
Old 03 July 2022, 11:08   #9
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
If you don't include math.h, then the compiler assumes (after a shitload of warnings)

Code:
int pow(int a,int b);
and it's not ending well. I don't see how you could even get 4 in the first place.

don't leave any warnings in your code, that's a golden rule (that most software don't respect and get hell out of it)
jotd is offline  
Old 03 July 2022, 11:28   #10
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
To be fair I only started to get a warning when I used pow() directly in the printf and was ignorning it as had only added that in the printf to quick "debug" what was happening. The following does not give any warnings when not including #include <math.h> but the result is still wrong.
Code:
double result = pow(base,power);
printf("result: %.2f\n", result);
prints:

Code:
result: 1074790400.00


Quote:
Originally Posted by jotd View Post
If you don't include math.h, then the compiler assumes (after a shitload of warnings)

Code:
int pow(int a,int b);
and it's not ending well. I don't see how you could even get 4 in the first place.

don't leave any warnings in your code, that's a golden rule (that most software don't respect and get hell out of it)
Sim085 is offline  
Old 03 July 2022, 11:34   #11
thomas
Registered User
 
thomas's Avatar
 
Join Date: Jan 2002
Location: Germany
Posts: 6,985
Quote:
Originally Posted by Sim085 View Post
To be fair I only started to get a warning when
Add -warn=-1 to the vbcc command line and -dontwarn= only for those you really don't need.
thomas is offline  
Old 03 July 2022, 12:36   #12
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
As far as I can see the behaviour shown here is absolutely to be expected.
  1. %lf and %f should make no difference. printf-like functions always take double precision arguments for float. An exception would be %Lf for long double, but on m68k this is the same as double.
  2. ISO-C defines that the return value of unknown functions, without a prototype, use the type
    int
    . The arguments of such a function are simply pushed by using the argument's type, promoted to
    int
    , if smaller (e.g. char or short). So the arguments for
    pow()
    are ok. The return value is garbage.
What happened here in detail, is this:
  • result = pow(base, power)
    correctly calculates the power of 2.0 and 2.0, but as the return type of pow is unknown, is is assumed as
    int
    .
  • As you are assigning the result of the "int" function to a double variable, it is then converted to double. The double precision result was $4010000000000000, with $40100000 in D0, which is 1074790400 and being converted to float. Sounds familiar?
  • Now
    pow(base, power)
    is called again, to calculate the last argument of
    printf()
    . Again the result is assumed as int and only the 32-bit word of $40100000 (MSW of the result) is pushed onto the stack. Next pushed on the stack are the 64 bits from
    result
    , and finally the format string pointer.
When printf is called is fetches a double argument for the first %f, which is 1074890400.0 (see above). Then is fetches another double argument for the second %f, which is $40100000 and a random 32-bit word from the stack. This random value modifies the mantissa enough to get small deviations, like 4.01 or 4.02.

All caused by missing the prototype for pow()!


Quote:
Originally Posted by bebbo View Post
well, it should print

a: 4.00 b: 4.00

even without any includes.
No, it shouldn't. At least not according to ISO-C. Maybe gcc recognizes some math functions automatically? But then it certainly doesn't work for new floating point functions.


Quote:
Originally Posted by Sim085 View Post
The following does not give any warnings when not includin
Code:
double result = pow(base,power);
printf("result: %.2f\n", result);
It definitely does. Show me the full the source where it doesn't. Here is mine:
Code:
frank@altair cat tst.c 
int main()
{
    double base = 2;
    double power = 2;
    double result = pow(base,power);
    printf("result: %.2f\n", result);
    return 0;
}
frank@altair vc +aos68k -o tst tst.c -lmieee
>    double result = pow(base,power);
warning 161 in line 5 of "tst.c": implicit declaration of function <pow>
>    printf("result: %.2f\n", result);
warning 161 in line 6 of "tst.c": implicit declaration of function <printf>
>    printf("result: %.2f\n", result);
warning 213 in line 6 of "tst.c": varargs function called without prototype in scope
phx is offline  
Old 03 July 2022, 12:54   #13
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
Quote:
Originally Posted by phx View Post
As far as I can see the behaviour shown here is absolutely to be expected.
Thank you for the detailed explanation. Now I understand better what is happening in the background.

Quote:
It definitely does. Show me the full the source where it doesn't. Here is mine:
After thomas comment I checked my make file and I do not have any warning flags included.

What are the suggested -dontwarn values to use?

Just adding -warn=-1 floods the compiler with warnings and many (sorry if saying so sound blasphemes ) do not seem to be important or referring to libraries I am using not wrote myself. Here are some examples:

Code:
struct Process *myProcess = NULL;
no deceleration of global variable <myProcess> before definition.
...
"dos/notify.h": member <nr_Reserved> does not have natural alignment.
Sim085 is offline  
Old 03 July 2022, 13:23   #14
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
Quote:
Originally Posted by Sim085 View Post
After thomas comment I checked my make file and I do not have any warning flags included.
Neither do I. You see my call to the vc-frontend above.

Quote:
What are the suggested -dontwarn values to use?
None. The default settings are usually fine.

Sometimes you want to use
-dontwarn=
for compiling bad source texts, or very old ones using K&R syntax, before you have to fix everything in it. For you own sources you should never suppress warnings, but fix them.

Quote:
Just adding -warn=-1 floods the compiler with warnings
Not sure why Thomas suggested it. IMHO it makes no sense.
Just use the default settings.
phx is offline  
Old 03 July 2022, 17:59   #15
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
As already mentioned it's highly adviceable to at least use the default warning level with your compiler. I usually go further, like thomas, and enable nearly every warning and then selectively disable the ones I don't want. Another tip is to make sure (most of) your code can be compiled with multiple compilers as they often catch different things.

VBCC is of course conformant here, and it's a classic mistake that's even covered by the comp.lang.c FAQ. (Not that I blame OP, I'm sure we've all made it)

Sidenote MSVC (19.32) outputs 0.00/0.00 when compiling without optimizations but 4.0/4.0 with for the original code indication "special knowledge" of certain functions (as allowed by the standard).
paraj is offline  
Old 03 July 2022, 21:43   #16
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
I have written this code in a separate solution and the only warning I am getting is in relation to vargs.

My code is as follows:
Code:
int main()
{
    double base = 2;
    double power = 2;
    double result = pow(base,power);
    printf("result: %.2f\n", result);
    return 0;
}
My make file is as follows:

Code:
CC=vc +aos68k
COPT = 
LIBS = -lamiga -lauto -lmieee
		
%.o : %.c
	$(CC) $(COPT) -c $< -o $@
		
HelloWorld : main.o
	$(CC) $^ -o $@ $(LIBS)
	
main.o: main.h
(left COPT empty).

I have tested this on vbcc version vbcc 0.904 (30.12.2014). Since this looks old I installed the latest one I could find on aminet, however, also on vbcc 0.907 (03.10.2019) I do not get any warning when using pow() without prototype.

Is something wrong with my setup? Everything compiles and I do get a warning, but not this particular one in relation to pow()
Sim085 is offline  
Old 03 July 2022, 23:14   #17
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
Quote:
Originally Posted by Sim085 View Post
also on vbcc 0.907 (03.10.2019) I do not get any warning when using pow() without prototype.
Wow... you're right! I just tested some old versions, including V0.9g, and these warnings are indeed missing with default settings.

Seems that they were made the default only with this year's release, V0.9h. So you may either want to update, or use
-warn=161
to enable it in older versions.
phx is offline  
Old 06 July 2022, 16:39   #18
Sim085
Registered User
 
Join Date: Apr 2009
Location: N/A
Posts: 962
Wanted to thank everyone for all the help. Have installed latest version and am getting some warnings in other areas which I am looking at. Many thanks
Sim085 is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Automatic scaling gives different result depending on palette thomas support.WinUAE 1 23 December 2016 20:18
Bought 1200 most disks result in guru meditation ramonsmits support.Hardware 10 10 November 2015 20:26
Which one would likely result in potentially better performance? Maren support.WinUAE 3 02 January 2011 08:32
Result!!! wilshy Retrogaming General Discussion 6 22 October 2009 20:27
WinUAE/AIB - Apps result in black screen Unregistered New to Emulation or Amiga scene 2 16 December 2001 20:31

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 16:35.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.09579 seconds with 13 queries