Link to home
Start Free TrialLog in
Avatar of gangclar
gangclar

asked on

CVS & MKS$

What's the mathematical formula behind the conversion for
BASIC CVS function and vice versa, MKS$.

CVS converts a single precision number to a 4-byte string
and MKS$ does the reverse.

Some results using the functions:

10 F2 6C 94 (HEX) ==  970529 (DEC)
80 80 80 80 (HEX) ==  -0.501961 (DEC)
A0 B0 C0 D0 (HEX) ==  -9.09953e+23 (DEC)
12 34 56 78 (HEX) ==  0.00326848 (DEC)
98 76 54 32 (HEX) ==  2.74602e-24 (DEC)
ASKER CERTIFIED SOLUTION
Avatar of y96andha
y96andha

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gangclar
gangclar

ASKER

It would be kind if you can explain the mathematics behind CVS
function using plain English. Actually I wanted to write a
similar function in C to convert data that was stored by program
written in Basic using the MKS$ function.

I would try to read the program that you've listed. Thanks.
OK. I could translate the code directly into C:

char a[4];
float g,f;
int e;
g=(a[2] & 0x7f) / (float)0x80;
g+=a[1] / (float)0x8000l;
g+=a[0] / (float)0x800000l;
e=((a[3] & 0x7f) << 1) + ((a[2] >>7) & 1) - 0x7f;
f=(1+g) * pow(2,e);
if(a[3] & 0x80)
    f=-f;

Untested code, but should work.

Plain English explanation:

Name the bytes in the string A, B, C, D. Bit 0 of byte A is called A0, and so on.

The number is written in binary form.

The mantissa is (binary):
1 C6 C5 ... C0 B7 B6 ... B0 A7 ... A0

The decimal point of the mantissa is after the first digit (after the 1).

The sign of the mantissa is stored in D7, 1 means negative.

The value of
   D6 D5 ... D0 C7
is the exponent added with 7F hexadecimal.


I hope you can understand my explanation. English is not my native language.


I do understand what you're saying, you wrote clear sentences
*8-).

However, I do have doubts immediately after reading your
comment. It would be great if you can explain an example or so.
Let me quote the example 10 F2 6C 94 (HEX).

According to what I understood from your explaination, byte D in
this case is 94(HEX) and D7(bit 7) would be 1, which tells that
this number is negative. But the conversion ended as +970529.

It would really help if you can list the working to convert the
above 4 bytes string to 970529(DEC). Thanks again !
You have made a mistake when typing in that value. I didn't get it to fit the description either, so I tested it in QBasic. The correct value is 10 F2 6C 49. You have mixed up the last two digits.

I've tried the C program that you've drafted. It doesn't produce the correct value. I used QBASIC CVS function to convert the value 970529 (DEC) and it gave me the 4-byte string 10 F2 6C 94 (HEX). The drafted program gave me -1.191478e-26 for the hex value quote above. I used Turbo C v3.0

Could you kindly provide me some help or reference to understand the mathematical logic of BASIC CVS and MKS$ function ? Thanks in advance.
I don't seem to get the same results. What version of QBasic are you using? I use the one that comes with Win95.

Executing this line results in 970529 as output from my QBasic interpreter:

PRINT CVS(CHR$(&H10) + CHR$(&HF2) + CHR$(&H6C) + CHR$(&H49))

If our Basic versions doesn't produce the same results, I'm afraid I cannot help you. I can only tell you how the one I have works.

I just managed to clear the air. For MS QBasic, please use CVSMBF instead of CVS which works for MS GWBasic. I tried on my copy of QBasic under WIN 95 and the results are produced correctly using CVSMBF.

Could you enlighten me on the conversion using C ? Thanks again !
OK, I don't have any good manual for this function, so I've analyzed it. This is my theory: (I copied most of it from above and then changed some of it)

Plain English explanation:

Name the bytes in the string A, B, C, D. Bit 0 of byte A is called A0, and so on.

The number is written in binary form.

The mantissa is (binary):
1 C6 C5 ... C0 B7 B6 ... B0 A7 ... A0

The decimal point of the mantissa is after the first digit (after the 1).

The sign of the mantissa is stored in C7, 1 means negative.

The value of
  D7 D6 D5 ... D0
is the exponent added with 81 hexadecimal.

I hope this is correct, I'll try and make some C code to test it.
I tried on the drafted program that you've suggested. By changing 10 F2 6C 94 to 10 F2 6C 49, I still don't get 970529.

I'm at my wits' end and look forward for your good news. Thanks again.
This is tested code to print 970529 with the CVSMBF format

static unsigned char a[4] = {0x10, 0xf2, 0x6c, 0x94};
float g,f;
int e;

g=(a[2] & 0x7f) / (float)0x80;
g+=a[1] / (float)0x8000l;
g+=a[0] / (float)0x800000l;
e=a[3] - 0x81;
f=(1+g) * pow(2,e);
if(a[2] & 0x80)
      f=-f;
printf("%g", f);


This is tested code to print 970259 with the CVS format

static unsigned char a[4] = {0x10, 0xf2, 0x6c, 0x49};
float g,f;
int e;


g=(a[2] & 0x7f) / (float)0x80;
g+=a[1] / (float)0x8000l;
g+=a[0] / (float)0x800000l;
e=((a[3] & 0x7f) << 1) + ((a[2] >>7) & 1) - 0x7f;
f=(1+g) * pow(2,e);
if(a[3] & 0x80)
      f=-f;
printf("%g", f);



Sorry, made an error in the last description, it should of course be 970529 there too.
I've tried the suggested codes using Turbo C v3.0. However, the result of conversion for 10 F2 6C 94 was 966898.1. Is there anything that I missed out ? Thanks again.
Now I've found the error. You typed in the code manually instead of copying it? The values of 0x8000l and 0x800000l are 0x8000 and 0x800000 respective, the last character is an L, for long constant.