We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

# CVS & MKS\$

on
Medium Priority
1,297 Views
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)
Comment
Watch Question

## View Solution Only

Commented:
Here is a function which you can substitute for CVS. It's not written in Visual Basic, but rather in QBasic, as that was the language where I found the CVS and MKS\$ functions.

I hope you can read the code and understand how it works.

You should be able to construct the inverse function from this source.

Please comment if you have any questions.

FUNCTION f (a AS STRING)
g = (ASC(MID\$(a, 3)) AND &H7F) / 2 ^ 7
g = g + ASC(MID\$(a, 2)) / 2 ^ 15
g = g + ASC(MID\$(a, 1)) / 2 ^ 23
f = (1 - ((ASC(MID\$(a, 4)) AND 128) / 64)) * (1 + g) * 2 ^ ((ASC(MID\$(a, 4)) AND &H7F) * 2 + ((ASC(MID\$(a, 3)) AND 128) / 128) - &H7F)
END FUNCTION

Not the solution you were looking for? Getting a personalized solution is easy.

Commented:
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.

Commented:
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

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

Commented:
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 !

Commented:
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.

Commented:
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.

Commented:
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.

Commented:
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 !

Commented:
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

I hope this is correct, I'll try and make some C code to test it.

Commented:
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.

Commented:
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);

Commented:
Sorry, made an error in the last description, it should of course be 970529 there too.

Commented:
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.

Commented:
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.
##### Thanks for using Experts Exchange.

• View three pieces of content (articles, solutions, posts, and videos)
• Ask the experts questions (counted toward content limit)
• Customize your dashboard and profile