Board index » cppbuilder » Simple multiply and divide

Simple multiply and divide

2007-11-19 02:06:38 AM
cppbuilder112
I'm having some difficulty when I multiply numbers.
WORD MyWord;
float MyFloat;
Lets say float is 12.345, I want to multiply it by 1000 so I can retain
everything right of the decimal.
i.e. 12.345 * 1000 would be 12345
MyWord = MyFloat * 1000;
MyWord is now 12000 instead of 12345;
So I figure I forgot the float on the multiplier and tried that.
MyWord = MyFloat * 1000.0;
MyWord is still 12000 instead of 12.345
What is going on and why?
TIA, Richard

Re:Simple multiply and divide

Hi Richard
Richard says:
Quote
I'm having some difficulty when I multiply numbers.

WORD MyWord;
float MyFloat;

Lets say float is 12.345, I want to multiply it by 1000 so I can retain
everything right of the decimal.
i.e. 12.345 * 1000 would be 12345

MyWord = MyFloat * 1000;
MyWord is now 12000 instead of 12345;

So I figure I forgot the float on the multiplier and tried that.
MyWord = MyFloat * 1000.0;
MyWord is still 12000 instead of 12.345
try:
MyWord = (float)(MyFloat * 1000.0);
Kind regards
Asger

Re:Simple multiply and divide

Since this all being done on a remote embedded device, debugging is a little
different so I can't really use the IDE and watches. What I did find is
that my float which is suppose to be 12.345 is indeed 12.000. This means
it's in my storage functions.
I have to take a float, break it down into 4 bytes, then store it.
I have to read it the same way, read 4 bytes and assemble it.
Which is the best way to do this? I was using the macros to get the
HighWord and Low Word then getting the High and Low Bytes of each word and
then store all 4 bytes.
When I read it, I would read the first two bytes and use MakeWord and then
the same for the next two bytes.
I would then take the two words and MakeLong to get my 4 bytes. I would
then Typecast the Long as a float. But this is where I'm loosing my digits.
Would it be better to just assign the float to an array then extract each
byte? I'm not sure how to do that, unions maybe? What is the Easiest,
cleanest way? Never used a union before.
union convert_float {
char byte;
uint upper_word;
uint lower_word;
double my_double;
float my_float;
} Convert;

{smallsort}

Re:Simple multiply and divide

Richard wrote:
Quote
So I figure I forgot the float on the multiplier and tried that.
MyWord = MyFloat * 1000.0;
MyWord is still 12000 instead of 12.345

What is going on and why?
No clue.
When I run this program with BC++3.1 (and TCE2006), all 4 numbers are 12345
#include <conio.h>
#include <stdio.h>
int main(void)
{
short a,b,c,d;
float f = 12.345;
a = f * 1000;
b = f * 1000.0;
c = (f * 1000.0);
d = ((f * 1000.0)+0.5);
printf( "\r\nA=%i B=%i C=%i D=%i\r\n",a,b,c,d);
getch();
return 0;
}

Re:Simple multiply and divide

Richard wrote:
Quote
I have to take a float, break it down into 4 bytes, then store it.
Why?
float f; // f is stored in 4 bytes at location &f
char* c = &f;
int i;
for( i=0; i<4; ++i )
sendfunction( c[i] );
Or, SendLong( (long*)&f );
fwrite( &f, sizeof(f), 1 filehandle );
Quote
I have to read it the same way, read 4 bytes and assemble it.
fread( &f, sizeof(f), 1, filehandle );
Quote
Would it be better to just assign the float to an array then extract each
byte?
Probably not.
Quote
Never used a union before.

union convert_float {
char byte;
uint upper_word;
uint lower_word;
double my_double;
float my_float;
} Convert;
That makes upper_word == lower_word == first 2 bytes of double == first 2 bytes of float
Double is 8 bytes, so you really want 8-byte values all round.
Also, in Intel type machines, low_word comes first.
union double_convertion {
double my_double;
char bytes;
WORD words;
DWORD dwords;
// struct dwords{
// DWORD lower_dword;
// DWORD upper_dword;
// };
} DoubleConvert;
union single_convertion {
float my_float;
char bytes;
struct{
uint lower_word;
uint upper_word;
}words;
} SingleConvert;
SingleConvert.words.lower_word

Re:Simple multiply and divide

I'm using an 80186 with 16 bit compiler.
I have tried this:
typedef union uREG32 /*16 bit register with word and byte access*/
{
float myfloat; /*access whole word */
struct /*access byte at a time*/
{
BYTE byte1;
BYTE byte2;
BYTE byte3;
BYTE byte4;
}byte;
}tREG32;
//To use it, declare a variable e.g.
tREG32 FloatData;
Then I write the individual bytes to eeprom.
FloatData.myfloat = 13.500;
WriteEEP(5,i,FloatData.byte.byte1); i++;
WriteEEP(5,i,FloatData.byte.byte2); i++;
WriteEEP(5,i,FloatData.byte.byte3); i++;
WriteEEP(5,i,FloatData.byte.byte4); i++;
Then when I read it Back:
Config.CylSize1 = FloatData.myfloat;
If I Print the results I get
FloatData.byte.byte1 = 0;
FloatData.byte.byte2 = 88;
FloatData.byte.byte3 = 65;
FloatData.byte.byte4 = 0;
FloatData.myfloat = 0.00;
So surely I'm not doing the struct and union correct.

Re:Simple multiply and divide

Ignore the comments on the union - Copy Paste and did not correct it.

Re:Simple multiply and divide

"Richard" <rwskinner@ccwipDOTnet>writes:
Quote
I'm having some difficulty when I multiply numbers.

WORD MyWord;
float MyFloat;

Lets say float is 12.345, I want to multiply it by 1000 so I can retain
everything right of the decimal.
i.e. 12.345 * 1000 would be 12345

MyWord = MyFloat * 1000;
MyWord is now 12000 instead of 12345;
The rules for evaluating the expression MyFloat*1000 are:
1) the value 1000 is converted to type float
2) the value of MyFloat is multiplied by the result of 1)
3) the result of 2) is converted to MyWord's type (WORD)
4) the result of 3) is assigned to MyWord
I'd expect a correct implementation to assign to MyWord either 12344
or 12345.
Quote
What is going on and why?
The C++ implementation is broken. Or your assumptions on the
variables' initial values are wrong.

Re:Simple multiply and divide

Bob,
I tried your union and I get the same results as my union did.
union single_convertion {
float my_float;
char bytes;
struct{
uint lower_word;
uint upper_word;
}words;
} SingleConvert;
//Assign a value
SingleConvert.my_float = 13.500;
//Write the individual bytes to eeprom
WriteEEP(5,i,SingleConvert.bytes); i++;
WriteEEP(5,i,SingleConvert.bytes); i++;
WriteEEP(5,i,SingleConvert.bytes); i++;
WriteEEP(5,i,SingleConvert.bytes); i++;
Print the results:
Byte0: 0 Byte1: 88 Byte2: 65 Byte3: 0
SingleConvert.my_float: 0.000000

Re:Simple multiply and divide

Richard wrote:
Quote
WriteEEP(5,i,FloatData.byte.byte1); i++;
You don't show 'i', but that looks suspect.
Would expect to see
In fact, 13.5 is 0,0,88,65, so you are off by one (the i+1)

Re:Simple multiply and divide

Again, up all night and missed the obvious. That's okay. I learned a few
things on Struct, Anonymous Unions, and using pointers to typecast.
"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote
Would expect to see

Re:Simple multiply and divide

Try this:
#include <iostream>
#include <iomanip>
using namespace std;
int main(void)
{
float MyWord;
float MyFloat = 12.345;
MyWord = MyFloat * 1000;
cout << setprecision(6) << MyWord << endl;
}
Hope this helps.
Richard wrote:
Quote

I'm having some difficulty when I multiply numbers.

WORD MyWord;
float MyFloat;

Lets say float is 12.345, I want to multiply it by 1000 so I can retain
everything right of the decimal.
i.e. 12.345 * 1000 would be 12345

MyWord = MyFloat * 1000;
MyWord is now 12000 instead of 12345;

So I figure I forgot the float on the multiplier and tried that.
MyWord = MyFloat * 1000.0;
MyWord is still 12000 instead of 12.345

What is going on and why?
TIA, Richard

Re:Simple multiply and divide

"Richard" < XXXX@XXXXX.COM >writes:
Quote
I have to take a float, break it down into 4 bytes, then store it.
I have to read it the same way, read 4 bytes and assemble it.
[snip]
Quote
Would it be better to just assign the float to an array then extract each
byte? I'm not sure how to do that, unions maybe? What is the Easiest,
cleanest way? Never used a union before.

union convert_float {
char byte;
uint upper_word;
uint lower_word;
double my_double;
float my_float;
} Convert;
Writing to one member of a union and then reading another causes the
program to have undefined behavior, so this is a no go.
Using a modern C++ compiler, I'd use the reinterpret_cast operator,
e.g.:
reinterpret_cast<unsigned char *>(&my_float)
, or go via void *:
static_cast<unsigned char *>(static_cast<void *>(&my_float))
You'll have to find out about the support of your version of Borlan
C++ for the cast operators.