0

Edit:

I have (test file in ascii) the following record in ascii: "000000000.00"
I need to output it ISO upon parsing it's counter part in BCD (the other test file in bcd/ebcdic).
I believe it takes 6 char in BCD and 11 in ascii.
So my need was something that could convert it back and forth.
First I thought of taking each chars, feed it to a convert function and convert it back hence my messed up question.

I hope i'm more clear.

Yain

Yain Tao
  • 71
  • 2
  • 6
  • Wait... Your function name is `bcdConvInt`, but you're passing it an `AnsiString`. Are you really looking for `BCDStringToInt`? Please [edit] your question to either correct the title or explain what exactly you're wanting to do, because the two combined don't make sense. Why are you taking a BCD value from a file and storing it in a string? It's not a string. – Ken White May 31 '13 at 15:20
  • You are right. I am tired from the ebcdic problem I tackled earlier. – Yain Tao May 31 '13 at 15:24
  • 1
    Please edit once again to provide a sample of the string you're trying to convert and the value you expect it convert to, as "(it somehow screw up my parsing") tells me your parsing is wrong. `StrToBCD` and `BCDToStr` have been around for a while, so I doubt the problem is with those functions. – Ken White May 31 '13 at 15:53
  • 3
    The task indeed isn't rare. It's so common that Delphi includes a [set of functions for handling everything](http://docwiki.embarcadero.com/RADStudio/en/BCD_Support_Routines), which is why few people write their own. The title talks about converting strings to BCD, which suggests you need `StrToBCD`. Your first paragraph talks about converting *integers* (not strings) to BCD, so you need `BcdToInteger`. Your mention `BcdToStr`, which does *neither* of the things you say you need. Please [edit] your question to make it consistent. Delete the parts that are not relevant to your immediate task. – Rob Kennedy May 31 '13 at 17:00
  • @Yain Why don't you take your head out of the sand and fix the root problem. – David Heffernan May 31 '13 at 18:47

3 Answers3

3

Dr. Peter Below (of Team B) donated these in the old Borland Delphi newsgroups a few years ago:

// NO NEGATIVE NUMBERS either direction.

// BCD to Integer
function BCDToInteger(Value: Integer): Integer;
begin
  Result := (Value and $F);
  Result := Result + (((Value shr 4) and $F) * 10);
  Result := Result + (((Value shr 8) and $F) * 100);
  Result := Result + (((Value shr 16) and $F) * 1000);
end;

// Integer to BCD
function IntegerToBCD(Value: Integer): Integer;
begin
  Result :=                   Value div 1000 mod 10;
  Result := (Result shl 4) or Value div  100 mod 10;
  Result := (Result shl 4) or Value div   10 mod 10;
  Result := (Result shl 4) or Value          mod 10;
end;
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Why would you use this rather than the built in functions? – David Heffernan May 31 '13 at 18:10
  • I didn't, and I didn't ask the question. The question specifically asked about doing it without the built-in functions, and I posted it in response to that question (which was quite a bit different than it is now). The poster then revised the question, but has failed to answer any of the follow up questions. Now it appears it's an issue with parsing, which wasn't even mentioned in the original question. I don't know what the actual problem is here, and until the poster clarifies it, I just left the answer. I'll delete it if needed. – Ken White May 31 '13 at 18:15
  • Hi, I ended up using those function you gave ading some casts and it worked. Thanks. – Yain Tao Jun 03 '13 at 15:28
0

As you may know, the ASCII codes of the numerals 0 through 9 are 48 through 57. Thus, if you convert each character in turn to its ASCII equivalent and subtract 48, you get its numerical value. Then you multiply by ten, and add the next number. In pseudo code (sorry, not a delphi guy):

def bcdToInt( string ):
  val = 0

  for each ch in string:
    val = 10 * val + ascii(ch) - 48; 

  return val; 

If your "string" in fact contains "true BCD values" (that is, numbers from 0 to 9, rather than their ASCII equivalent 48 to 57), then don't subtract the 48 in the above code. Finally, if two BCD values are tucked into a single byte, you would access successive members with a bitwise AND with 0x0F (15). But in that case, Ken White's solution is clearly more helpful. I hope this is enough to get you going.

Floris
  • 45,857
  • 6
  • 70
  • 122
0

functions below work for 8 digit hexadecimal and BCD values.

function BCDToInteger(Value: DWORD): Integer;
const Multipliers:array[1..8] of Integer=(1, 10, 100, 1000, 10000, 100000, 1000000, 10000000);
var j:Integer;
begin
 Result:=0;
 for j:=1 to 8 do //8 digits
 Result:=Result+(((Value shr ((j-1)*4)) and $0F) * Multipliers[j]);
end;//BCDToInteger

function IntegerToBCD(Value: DWORD): Integer;
const Dividers:array[1..8] of Integer=(1, 10, 100, 1000, 10000, 100000, 1000000, 10000000);
var j:Integer;
begin
 Result:=0;
 for j:=8 downto 1 do //8 digits
 Result:=(Result shl 4) or ((Value div Dividers[j]) mod 10);
end;//IntegerToBCD
suat dmk
  • 116
  • 1
  • 2