AuthorMessage
Meka][Meka
Unstopable
Posts: 700

anyone see why this aint working??
Code:

procedure ShowByteSize;
var
  i : Integer;
  s : string;
begin
  if ComboBox1.Text = 'B' then
    i := StrToInt(Edit4.Text)
  else if ComboBox1.Text = 'KiB' then
    i := StrToInt(Edit4.Text) * 1024
  else if ComboBox1.Text = 'MeB' then
    i := (StrToInt(Edit4.Text) * 1024) * 1024
  else if ComboBox1.Text = 'GiB' then
    i := ((StrToInt(Edit4.Text) * 1024) * 1024) * 1024
  else if ComboBox1.Text = 'TeB' then
    i := (((StrToInt(Edit4.Text) * 1024) * 1024) * 1024) * 1024
  else if ComboBox1.Text = 'PeB' then
    i := ((((StrToInt(Edit4.Text) * 1024) * 1024) * 1024) * 1024) * 1024;
  s := IntToStr(i);
  ShowMessage(s);
end;

Mickey
Ametuar
Posts: 115

The problem is [u:89b728186d]overflow in conversions or arithmetic operations[/u:89b728186d].
Watch aritmetic ranges. Using Integer you can store max 2GB - 1 byte = 2147483647 Bytes!!! = 2^31-1 ~~ 2.14 * 10^9
1PeB = 1125899906842624 Bytes = 2^50 ~~ 1.12 * 10^15
Having a look at the table below which is from Delphi Help we realize we should use Int64 to store PeB big numbers:
Generic integer types for 32-bit implementations of Delphi
Type   /   Range   /   Format
Integer   :   -2147483648..2147483647   signed 32-bit
Cardinal   :   0..4294967295   unsigned 32-bit
Fundamental integer types include Shortint, Smallint, Longint, Int64, Byte, Word, and Longword.
Fundamental integer types
Type   /   Range   /   Format
Shortint   :   -128..127   signed 8-bit
Smallint   :   -32768..32767   signed 16-bit
Longint   :   -2147483648..2147483647   signed 32-bit
Int64   :   -2^63..2^63-1   signed 64-bit
Byte   :   0..255   unsigned 8-bit
Word   :   0..65535   unsigned 16-bit
Longword   :   0..4294967295   unsigned 32-bit
Let's try the code now. I shortened a bit. I could see a lot of parenthesis which could be neglected due to the fact multiplication is commutative and associative. Of course it is not a problem but why not to make it shorther? So it can be something like this:
Code:
procedure TForm1.ShowByteSize;
var
  i : Int64;
  s : string;
begin
  i := StrToInt(Edit4.Text);
  if ComboBox1.Text = 'KiB' then
    i := i * 1024
  else if ComboBox1.Text = 'MeB' then
    i := i * 1024 * 1024
  else if ComboBox1.Text = 'GiB' then
    i := i * 1024 * 1024 * 1024
  else if ComboBox1.Text = 'TeB' then
    i := i * 1024 * 1024 * 1024 * 1024
  else if ComboBox1.Text = 'PeB' then
    i := i * 1024 * 1024 * 1024 * 1024 * 1024;
  s := IntToStr(i);
  ShowMessage(s);
end;

It hasn't worked yet :(
The problem is:
Try to paste this in your code anywhere and compille:
Code:
  i := 1 * 1024 * 1024 * 1024; // This is OK and can be calculated
  i := 2 * 1024 * 1024 * 1024; // Overflow :(
Error: Overflow in conversion or arithmetic operation.
You'll get error at compillation.
It seems that Delphi built in routines cannot multiply such big numbers :( Too bad.
Solution: We need to make our own multiplying routine for big numbers.
I could see some cool maths routines I got from www.torry.net. If you cannot find tell me and I'll have a look.
I hope it helped. Good luck.
Meka][Meka
Unstopable
Posts: 700

yep i had tried the in64 and still had the same problem, i guessed it was a delphi problem, but wanted to make sure, thanks...
Meka][Meka
Unstopable
Posts: 700

ok i've messed around for 10mins and finally came to the concliusion its my fault, so i have finally found the error i (we) was making...
Code:

procedure ShowByteSize;
var
  i : Extended;
  s : String;
begin
  if ComboBox1.Text = 'B' then
    i := StrToFloat(Edit1.Text)
  else if ComboBox1.Text = 'KiB' then
    i := StrToFloat(Edit1.Text) * 1024
  else if ComboBox1.Text = 'MeB' then
    i := (StrToFloat(Edit1.Text) * 1024) * 1024
  else if ComboBox1.Text = 'GiB' then
    i := ((StrToFloat(Edit1.Text) * 1024) * 1024) * 1024
  else if ComboBox1.Text = 'TeB' then
    i := (((StrToFloat(Edit1.Text) * 1024) * 1024) * 1024) * 1024
  else if ComboBox1.Text = 'PeB' then
    i := ((((StrToFloat(Edit1.Text) * 1024) * 1024) * 1024) * 1024) * 1024;
  s := FloatToStr(i);
  ShowMessage(s);
end;

-/Meka][Meka
Mickey
Ametuar
Posts: 115

Cool. 8)
Of course, you don't need to use integers. Sorry for not mentioning that.
Anyway if I want fast code I would use Integers with some asm multiply routines but here is not needed.
This way you did is easier. If you omit those parenthesis as I did abobe would be nicer but it is up to you.  :wink:
Code:
procedure TForm1.ShowByteSize;
var
  i : Extended;
  s : string;
begin
  i := StrToFloat(Edit4.Text);
  if ComboBox1.Text = 'KiB' then
    i := i * 1024
  else if ComboBox1.Text = 'MeB' then
    i := i * 1024 * 1024
  else if ComboBox1.Text = 'GiB' then
    i := i * 1024 * 1024 * 1024
  else if ComboBox1.Text = 'TeB' then
    i := i * 1024 * 1024 * 1024 * 1024
  else if ComboBox1.Text = 'PeB' then
    i := i * 1024 * 1024 * 1024 * 1024 * 1024;
  s := FloatToStr(i);
  ShowMessage(s);
end;

bluebear
n00b
Posts: 32

^^^If its calculations that are done often; for example in the userlist of a client wich updates alot. I would use bitwise operations instead much faster'
Cpp ->
Code:
#ifdef __BORLANDC__
  #pragma argsused
int main( int argc, char * argv[] )
{
  unsigned long result, bytes;
  bytes = 792723456; /* 756 Mbytes */
  /* Normal calcs */
  result = ( bytes / 1024 ); /* bytes to kbytes */
  cout << "Normal calc: " << result << " KB" << endl;
  result = ( ( bytes / 1024 ) / 1024 ); /* bytes to mbytes */
  cout << "Normal calc: " << result << " MB" << endl;
  // bitwise
  result = bytes >> 10; /* bytes to kbytes */
  cout << "Bitwise calc: " << result << " KB" << endl;
  result = bytes >> 20; /* bytes to mbytes */
  cout << "Bitwise calc: " << result << " MB" << endl;
  return 0;
}

Meka][Meka
Unstopable
Posts: 700

ah but remember this is pascal section, and, i only need it to check once in a while, when i click check button thanks neways 
Mickey
Ametuar
Posts: 115

Yep BlueBear how right you are. Working on numbers with base 2 and 16 we can use shift operators:
shl - bitwise shift left (division)
shr - bitwise shift right
x shl 10 = x * (2^10) = x*1024
x shl 20 = x * (2^20) = x*1024*1024
etc.
Shifting  is the fastest way, faster than multiplication.
The code would be this:
Code:
procedure ShowByteSize;
var
  i : Int64;
  s : string;
begin
  i := StrToInt(Edit4.Text);
  if ComboBox1.Text = 'KiB' then
    i := i shl 10
  else if ComboBox1.Text = 'MeB' then
    i := i shl 20
  else if ComboBox1.Text = 'GiB' then
    i := i shl 30
  else if ComboBox1.Text = 'TeB' then
    i := i shl 40
  else if ComboBox1.Text = 'PeB' then
    i := i shl 50;
  s := IntToStr(i);
  ShowMessage(s);
end;