Floating point type conversions
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Floating point type conversions
Being rather new at this I'm having trouble controlling the mode in which
calculations are done.
In the following 'MOD'like expression - to reduce an angle X to the range 0 to
2pi - I need (X/_2pi) to be done as floating point, then truncated to an
integer, then multiply by _2pi in floating point.
X = X - (X/_2pi)*_2pi
Tried various configurations and tricks without success and ended up with Tod's
'fix' function.
function fix(x as single) as integer
return x
endfunction
X = X - fix(X/_2pi)*_2pi
Works nicely - but is there a 'built-in' way to do the same thing?
Chris
calculations are done.
In the following 'MOD'like expression - to reduce an angle X to the range 0 to
2pi - I need (X/_2pi) to be done as floating point, then truncated to an
integer, then multiply by _2pi in floating point.
X = X - (X/_2pi)*_2pi
Tried various configurations and tricks without success and ended up with Tod's
'fix' function.
function fix(x as single) as integer
return x
endfunction
X = X - fix(X/_2pi)*_2pi
Works nicely - but is there a 'built-in' way to do the same thing?
Chris
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
The rules for expression evaluation are very straight forward. In any statement
the first variable, constant or function encountered when scanning from left to
right determine how the expression will be evaluated. So in your example if X
is a SINGLE, the whole expression will be evaluated in floating point.
Among most languages the rules can vary, and we chose the simplest method.
BASIC does not have type casting like C, and while we could add a built in
fix(x) function, an explicit function in BASIC is the proper way to do it now.
From a performance perspective, it adds a BL (call) and BX LR (return), but
that's only a hundred nano-seconds or so, and with a floating point divide
involved not a large percentage penalty.
the first variable, constant or function encountered when scanning from left to
right determine how the expression will be evaluated. So in your example if X
is a SINGLE, the whole expression will be evaluated in floating point.
Among most languages the rules can vary, and we chose the simplest method.
BASIC does not have type casting like C, and while we could add a built in
fix(x) function, an explicit function in BASIC is the proper way to do it now.
From a performance perspective, it adds a BL (call) and BX LR (return), but
that's only a hundred nano-seconds or so, and with a floating point divide
involved not a large percentage penalty.
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
True there are no type casts in BASIC but VB has had built-in coersion functions
(CInt(), CLng(), CSng(), CDbl()) for a very long time, and they are the
equivilent of type casts.
As for evaluation order and type promotion, that's pretty interesting... so...
(2 * 1.5) equals 2, because the first operand is an integer?
Then do sub-expressions count as statements?
Is (2 * 1.5) + (1.5 * 2) equal to 5, because the first operand to the second
sub-expression is floating-point? Or is it 4 because the first operand
encountered in the entire line of code is an integer?
-MM
(CInt(), CLng(), CSng(), CDbl()) for a very long time, and they are the
equivilent of type casts.
As for evaluation order and type promotion, that's pretty interesting... so...
(2 * 1.5) equals 2, because the first operand is an integer?
Then do sub-expressions count as statements?
Is (2 * 1.5) + (1.5 * 2) equal to 5, because the first operand to the second
sub-expression is floating-point? Or is it 4 because the first operand
encountered in the entire line of code is an integer?
-MM
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
> Is (2 * 1.5) + (1.5 * 2) equal to 5, because the first operand to the second
sub-expression is floating-point? Or is it 4 because the first operand
encountered in the entire line of code is an integer?
That would be equal to 4 as an integer, as the whole expression would be
evaluated as an integer.
To make it 6.0 as a float
(2.0 * 1.5) +(1.5 * 2) would do it.
As for built in functions, for fix() or maybe ceiling(), those may come later,
as they are functions of the compiler and not the firmware. We can easily
change the compiler. But we took on some big changes for this revision and will
come back later and add more as needed. The big change is float itself, but we
also added compound operators, which I have to admit I use all the time now,
like i += 1
And also added access to the printf/sprintf which were in the firmware all
along, just didn't have a hook to use them before.
sub-expression is floating-point? Or is it 4 because the first operand
encountered in the entire line of code is an integer?
That would be equal to 4 as an integer, as the whole expression would be
evaluated as an integer.
To make it 6.0 as a float
(2.0 * 1.5) +(1.5 * 2) would do it.
As for built in functions, for fix() or maybe ceiling(), those may come later,
as they are functions of the compiler and not the firmware. We can easily
change the compiler. But we took on some big changes for this revision and will
come back later and add more as needed. The big change is float itself, but we
also added compound operators, which I have to admit I use all the time now,
like i += 1
And also added access to the printf/sprintf which were in the firmware all
along, just didn't have a hook to use them before.
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
Not exactly ...
CInt() etc. are very different from type casts.
Typecasting an item does not generate any code. It is just a way of telling a
compiler to pretend the item is a different type to circumvent type-checking.
You can only typecast one type to another type if both types have the same
number of bits. The resulting bit pattern is unchanged.
Regards,
Chris Burrows
Astrobe v4.2: Oberon for Cortex-M3 Development System
http://www.astrobe.com
CInt() etc. are very different from type casts.
Typecasting an item does not generate any code. It is just a way of telling a
compiler to pretend the item is a different type to circumvent type-checking.
You can only typecast one type to another type if both types have the same
number of bits. The resulting bit pattern is unchanged.
Regards,
Chris Burrows
Astrobe v4.2: Oberon for Cortex-M3 Development System
http://www.astrobe.com
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
> Typecasting an item does not generate any code. It is just a way of
> telling a compiler to pretend the item is a different type to
> circumvent type-checking.
Fair enough. The coersion functions do sign extension and in some cases round
or truncate, no guarantee -- not even a suggestion, really -- that the bits come
out the same.
> You can only typecast one type to another type if both types have
> the same number of bits. The resulting bit pattern is unchanged.
Consider this tiny program:
int main(void)
{
char c = 'x';
int i = (int)c;
c = (char)i;
return i;
}
This builds without errors/warnings, the function main() returns 120 (ASCII for
'x'). I believe it's a feature of the type cast, to zero-pad when casting to a
larger type or truncate when casting to smaller, but regardless, clearly the
size of the variable being cast does not have to match the size of the type to
which it is being cast.
-MM
> telling a compiler to pretend the item is a different type to
> circumvent type-checking.
Fair enough. The coersion functions do sign extension and in some cases round
or truncate, no guarantee -- not even a suggestion, really -- that the bits come
out the same.
> You can only typecast one type to another type if both types have
> the same number of bits. The resulting bit pattern is unchanged.
Consider this tiny program:
int main(void)
{
char c = 'x';
int i = (int)c;
c = (char)i;
return i;
}
This builds without errors/warnings, the function main() returns 120 (ASCII for
'x'). I believe it's a feature of the type cast, to zero-pad when casting to a
larger type or truncate when casting to smaller, but regardless, clearly the
size of the variable being cast does not have to match the size of the type to
which it is being cast.
-MM
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
No. C is not a typesafe language so it is easy to be fooled. What you are seeing
here is the automatic type *conversion* that happens when you mix ints and chars
in C. The typecasts are ignored - they are as redundant as saying
int j = (int)i;
The following generates identical code:
int main(void)
{
char c = 'x';
int i = c;
c = i;
return i;
}
The sort of situation where you need to use a typecast in C is when the
automatic conversion rules are not suitable. e.g.
double pi = (double)22/7;
Regards,
Chris.
here is the automatic type *conversion* that happens when you mix ints and chars
in C. The typecasts are ignored - they are as redundant as saying
int j = (int)i;
The following generates identical code:
int main(void)
{
char c = 'x';
int i = c;
c = i;
return i;
}
The sort of situation where you need to use a typecast in C is when the
automatic conversion rules are not suitable. e.g.
double pi = (double)22/7;
Regards,
Chris.
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
Maybe you could add an 'official' set of Fix, Float(?), Ceil, Floor, etc
functions to BASIClib Bruce?
Tods Math.lib functions seem to work OK. I'm sure he'd would be happy to share
functions to BASIClib Bruce?
Tods Math.lib functions seem to work OK. I'm sure he'd would be happy to share
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
Hi Tod,
floor(-2.0) returns -3. From the defn I expected -2..
cp
function floor(x as single) as single
// floor returns the largest integral single value not greater than fparam
// floor of 3.8 is 3.0, floor of -2.3 is -3.0
return fix(x-if(x<0,1,0))
endfunction
floor(-2.0) returns -3. From the defn I expected -2..
cp
function floor(x as single) as single
// floor returns the largest integral single value not greater than fparam
// floor of 3.8 is 3.0, floor of -2.3 is -3.0
return fix(x-if(x<0,1,0))
endfunction
-
- Posts: 1462
- Joined: Fri Oct 19, 2012 5:11 am
Re: Floating point type conversions
I took a quick look at adding Cint, CSng, int or fix to the compiler. My
initial assumption was that the compiler could use the automatic truncation used
in the automatic conversion of single to integer.
However VB's Cint rounds the number. int and fix return the same type as are
passed to the routine. In all these cases ARMbasic would either have to add
something to the firmware or be different than VB.
As your post below shows the pitfalls of putting things in firmware (ie bugs),
the preferred solution is to put these functions into a library.
> floor(-2.0) returns -3. From the defn I expected -2..
> cp
>
> function floor(x as single) as single
> // floor returns the largest integral single value not greater than fparam
> // floor of 3.8 is 3.0, floor of -2.3 is -3.0
> return fix(x-if(x<0,1,0))
> endfunction
>
initial assumption was that the compiler could use the automatic truncation used
in the automatic conversion of single to integer.
However VB's Cint rounds the number. int and fix return the same type as are
passed to the routine. In all these cases ARMbasic would either have to add
something to the firmware or be different than VB.
As your post below shows the pitfalls of putting things in firmware (ie bugs),
the preferred solution is to put these functions into a library.
> floor(-2.0) returns -3. From the defn I expected -2..
> cp
>
> function floor(x as single) as single
> // floor returns the largest integral single value not greater than fparam
> // floor of 3.8 is 3.0, floor of -2.3 is -3.0
> return fix(x-if(x<0,1,0))
> endfunction
>