i try to put 8 byte character into the equation causing a lot of error,what i'm supposed to do to make sure the equation can take the static value and produce output in the 8 bytes.
#include <math.h>
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
void voltage_measure(void);
void main(void) {
voltage_measure();
}
void voltage_measure(void) {
char Van1[8],VA;
char Vbn[8],VB;
char Vcn[8],VC;
char AC[4],ac;
char BC[4],bc;
char AB[4],ab;
double Vab1,Vab2,Vbc1,Vbc2,Vac1,Vac2;
double Vab[8],Vbc[8],Vac[8];
Van1[0]=0xF0;
Van1[1]=0x00;
Van1[2]=0x00;
Van1[3]=0x00;
VA=0x000000F0;
Vbn[0]=0x78;
Vbn[1]=0x00;
Vbn[2]=0x00;
Vbn[3]=0x00;
VB=0x78;
Vcn[0]=0x3C;
Vcn[1]=0x00;
Vcn[2]=0x00;
Vcn[3]=0x00;
VC=0x3C;
AB[0]=0xB4;
AB[1]=0x00;
ab=0xB4;
AC[0]=0x2D;
AC[1]=0x00;
ac=0x2D;
BC[0]=0x5A;
BC[1]=0x00;
bc=0x5A;
Vab1=(VB*sin(ab))*(VB*sin(ab)) ;
Vab2=(VA+(VB*cos(ab)))*(VA+(VB*cos(ab)));
Vab[4]=sqrt(Vab1+Vab2);
Vbc1=(VC*sin(bc))*(VC*sin(bc));
Vbc2=(VB+(VC*cos(bc)))*(VB+(VC*cos(bc))) ;
Vbc[4]=sqrt(Vbc1+Vbc2);
Vac1=(VC*sin(ac))*(VC*sin(ac));
Vac2=(VA+(VC*cos(ac)))*(VA+(VC*cos(ac)));
Vac[4]=sqrt(Vac1+Vac2);
}
This is what I have understood as yet,
you want to do arithmetic with double precision that has several parameters
you would like to store the parameters in char variables (maybe to save on space?)
I don't know why you try to write VA=0x000000F0; when its a char (1 byte) variable
the static value you refer are probably the constants VA etc
It might be useful to have all these working in the arithmetic at double precision
when you use the sin and sqrt kind of functions, they will work at double anyways
you do not have a main function listed here;
it would be there in your actual file (that compiles this code)
so, i am also assuming you have things like math.h included
and the math library on the compile command
that is, you do get the binary compiled without errors
maybe you can elaborate the problem you are facing a little more?
Update from comment 1.
When you say, "character with 8 byte array" -- are you trying to create a double with an 8 char array?
Update from comment 2.
If your answer is in double, you can catch it in a double variable.
A double is already 8-bytes (on most platforms).
Is there a special reason to get it into a char array or a byte array?
Update from comment 3.
The link error implies you did include a math library for the linking.
The header just gives function prototypes for compilation.
With gcc, it would be -lm on the command line.
Update from comment 4.
To convert a double to an integer value check this page,
How can I convert a floating-point value to an integer in C?
Is the trouble that plain char on your machine is signed, so numbers such as 0xF0 are treated as -16 instead of +240? Did you know that on some machines, this is what will happen?
Concerning your link error you mentioned in the comments: including math.h is not enough, you have to tell the linker to add the library as well. Try adding "-lm" in your command line.
Related
I write c embedded on STM32F437VI. At some point, I need to parse some strings that contain numbers, as float numbers. I use atof and it works always with the correct result, except for this one weird case. If the string is 0 or 0.0 it gives 2.
I have included stdlib.h and even tried (float)atof() to typecast, but for some weird reason, the float variable has always the value 2 from the atof("0") operation and the double value has the correct 0.
Why is this happening? Thank you all in advance.
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
char test[] = "0";
float val1;
double val2;
val1 = atof(test);
val2 = atof(test);
return 0;
}
I expect the obvious result of 0 to the float variable as well, but it keeps getting the fixed 2 value.
UPDATE:
This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option
"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".
Could this affect this issue?
As the MCV example is concerned, in main.c I have the above code section and I got the results mentioned.
Can anybody think of any reason atof() behaves in this way?
Of course I have used online c compiler as well with the exact same code and the result is of course 0. I guess if something was very very wrong with the stdlib library, then atof() would not work for all the other cases as well. But it fails only for "0" and only with the result 2 assigned to the float variable.
I watch the variables realtime with Ozone debugger software.
Could the reason be the floating point implementation on STM32F4 mcu used? A missing parameter in the custom Makefile or something like that?
First, your question lacks a Minimal, Complete, and Verifiable example.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char test[] = "0";
float val1;
double val2;
val1 = atof(test);
printf("%f\n", val1);
val2 = atof(test);
printf("%f\n", val2);
}
Output:
0.000000
0.000000
<°)))<()
Or your standard library implementation is fubar.
It looks like the cause of your problem is in the updated question text:
UPDATE: This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option
"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".
Assuming these options are changes vs the defaults, what you're doing is telling the compiler to generate code for a different ABI from your toolchain's library ecosystem. The code generated for main expects the result of atof in a floating point register, but atof is using the standard ABI, which passes floating point arguments and return values in general-purpose registers. Thus, main is just reading whatever junk happens to be left in the floating point registers used for return values.
See if your problem goes away if you remove -mfloat-abi=hard. If so, you've probably found your problem. You need to either build a toolchain and libraries for the hardfloat ABI, or stick with the default non-hardfloat calling convention.
I've read the questions regarding the implementation of rounding in C, inspired by MATLAB round function and I followed their advice but the result is not at all what it should be. Here's part of my code regarding this issue:
movmean_h[i]=(double)sum/(f-b);
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
movmean_h[i]=(double)round(movmean_h[i]*n)/n;
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
And part of the result is like this(this code is run in a loop):
movmean_h[10261]=2.283693e-13 movmean_h[10261]=1.668138e-06
movmean_h[10261]=2.283693e-13 movmean_h[10261]=1.668138e-06
movmean_h[10262]=2.288172e-13 movmean_h[10262]=1.483963e-06
movmean_h[10263]=2.292687e-13 movmean_h[10263]=-8.838173e-07
movmean_h[10264]=2.297219e-13 movmean_h[10264]=0.000000e+00
movmean_h[10265]=2.292835e-13 movmean_h[10265]=2.138378e-06
movmean_h[10266]=2.288319e-13 movmean_h[10266]=1.409754e-06
movmean_h[10267]=2.283839e-13 movmean_h[10267]=0.000000e+00
movmean_h[10268]=2.279412e-13 movmean_h[10268]=-2.147484e-06
movmean_h[10269]=2.275056e-13 movmean_h[10269]=-2.147484e-06
movmean_h[10270]=2.270787e-13 movmean_h[10270]=-2.147484e-06
movmean_h[10262]=2.288172e-13 movmean_h[10262]=1.483963e-06
movmean_h[10263]=2.292687e-13 movmean_h[10263]=-8.838173e-07
movmean_h[10264]=2.297219e-13 movmean_h[10264]=0.000000e+00
movmean_h[10265]=2.292835e-13 movmean_h[10265]=2.138378e-06
movmean_h[10266]=2.288319e-13 movmean_h[10266]=1.409754e-06
movmean_h[10267]=2.283839e-13 movmean_h[10267]=0.000000e+00
movmean_h[10268]=2.279412e-13 movmean_h[10268]=-2.147484e-06
movmean_h[10269]=2.275056e-13 movmean_h[10269]=-2.147484e-06
movmean_h[10270]=2.270787e-13 movmean_h[10270]=-2.147484e-06
The answers do not match at all, not in order and not in the decimals, which in theory they would match.
And 'n' is defined as:
long int n=pow(10,15);
So my question is why my code is wrong, or is there something I'm missing?
By the way I am writing my C code for a MATLAB mex-file.
Code lacked a declaration of declaration of double round(). Older compilers allow this, yet interpret the result then an int. Code output is then quite bizarre. The hint, for me, was that many nearby double inputs had the same result.
// add
#include <math.h>
10^15 doesn't fit into a long int on a Windows machine. Use a double.
double n = pow(10, 15);
movmean_h[i]=(double)sum/(f-b);
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
movmean_h[i]=round(movmean_h[i]*n)/n;
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
New to C, I've been trying to convert a hex input with this code. The input argv[1] I've been giving it is 0xabcd123. It has only given me 0 outputs. I have also tried using atoi as well as varying the types of outputs. Why does it only print 0? Here is the code, thanks
#include <stdio.h>
#include <stdlib.h>
typedef union{
double num;
float f;
} U;
int main(int argc, char*argv[])
{
U u;
u.num = strtod(argv[1], NULL);
printf("%e\n", u.f);
return 0;
}
result is platform dependent!
I believe its returning 0 on one system because of byte order. when you write to the value as a double but then read it as a float, you may be reading the top or bottom half of the double, depending on the architecture. on one system it's the empty top half of the double, on another its the bottom half which contains value.
either way, with a union, you should never expect to write any value as one type, and read back as another and get reliable results. as you have discovered :) unions aren't magic type converters, they simply allow you to save space when you know you have one type of value at a time.
num is declared as int. So printf("%d", u.num) or double num
First, please kindly reformat your code so that everyone can read it easily.
Second, the type of your u.num is double, so utilize %f or %lf instead of %d
Third, as shown in this codepad http://codepad.org/JSSJEKOn, your code is correct and it must obviously print the expected result. So I think that the error is not here but somewhere else in your source file. Please give us more information
I want to simply pass a variable from assembly over to C and C over to assembly.
The problem is i don't want to use fixed memory addressing (IE. putting the value in a specific location and then using a pointer to access that specific location).
I was initially thinking that i could use registers, but there are only 16 in total! I may have more than 16 values which i want to pass over.
So the next thing i can think of is pushing the values onto the stack. But does this mean i have to use inline assembly to access it in C? something like this:
asm ( assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
Is there any other way to go about this? Can anyone give me a REALLY simple example of putting something on the stack, and then accessing it in C code?
Assembly Noob!
Can you declare a regular C function, call it from C, and allow the compiler to handle the arguments automatically (according to whatever your local convention is)?
If so, you just implement that function using asm, and refer to the named C argument list variables directly.
Eg, using the 68881's fsinx instruction:
float my_fsinx(float angle)
{
float result;
asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
return result;
}
This example is based on the GCC Extended Asm docs, where you should be able to find some more examples.
Now extended, as per the comment, to handle variable numbers of arguments via a simple pointer & count ...
float my_fsinx_sum(float *angles, int num_angles)
{
float result, sum;
int i;
for (i=0, sum=0; i < num_angles; ++i)
{
asm ("fsinx %1,%0" : "=f" (result) : "f" (angles[i]));
sum += result;
}
return sum;
}
No, I'm not sure why you'd want to sum the sines of a bunch of angles either, but hopefully you get the idea. I haven't tried this, so it's possible the angles[i] value needs to be copied out into a local float variable before the asm - try it and see.
You could also use a variable argument-list function, but that's a little more complicated. Without more detail on what you're trying to accomplish and what you've already tried, I can't guess which is better.
Edit --
OK, now I've seen your comment above, you definitely don't want a variable argument-list function: those still have a number of arguments hardcoded at the call site.
when i execute the below code, the compiler returns the message "(.text+0x31): undefined reference to 'sqrt'". but if i take away the q* the compiler correctly gives me 8.000000
i'm trying to get the program to multiply the INCREMENT by 1 (and eventually 2 and 3 when i write the loop in).
how come the below doesn't work?
#include <stdio.h>
#include <math.h>
#define INCREMENT 64
int main ()
{
int q = 1;
printf("%f", sqrt(q*INCREMENT));
return 0;
}
You probably need to link to the math library. (though I thought visual C++ does this automatically...)
The reason why it works without the q is because the compiler is optimizing out the sqrt since it's a constant.
The code is correct c code. I tested it under vs 2010 and it returned the value 8. However it is not correct c++ code. sqrt becomes ambigueous when the argument is an integer. Is it possible that your source file has a .cpp extension, instead of a .c extension?