Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I best convert an integer to a floating point value without assigning to a variable?

Tags:

delphi

I would like to know how to convert from an integer to a floating point value, without assigning to an intermediate variable. The code in question looks like this:

Format('Theoretical peak scaling %6.2f', [ThreadCount])

This obviously fails at runtime because ThreadCount is an integer.

I tried the obvious

Format('Theoretical peak scaling %6.2f', [Double(ThreadCount)])

and the compiler rejects that with

E2089 Invalid typecast

I know I can write

Format('Theoretical peak scaling %6.2f', [ThreadCount*1.0])

but that reads poorly and will just tempt a future maintainer to remove the multiplication in error.

Does anyone know of a clean way to do this without an intermediate variable, and in way that makes the codes intent clear to future readers?

like image 259
David Heffernan Avatar asked Apr 17 '13 19:04

David Heffernan


3 Answers

This maybe feels silly... but if it's an integer why not just :

Format('Theoretical peak scaling %3d.00', [ThreadCount]);

It's not like you're ever going to have anything but zeroes after the decimal point, right?

like image 132
J... Avatar answered Oct 05 '22 23:10

J...


You have the alternative to use a record helper for intrinsic types:

type
  TIntHelper = record helper for Integer
    function AsFloat : Double;
  end;

function TIntHelper.AsFloat: Double;
begin
  Result := Self;
end;

Format('Theoretical peak scaling %6.2f', [ThreadCount.AsFloat])

This was added in XE3, but with some restrictions from Embarcadero. Since only one helper can be in scope, Emarcadero suggests that this feature is for them to use inside the RTL only.

Quote from Marco Cantu:

  • we advise against writing your own (although you might want to do this as a temporary measure for types we don't support)

  • the reason is not just the one helper per class rule, but also that this behavior change in the future, with different compiler mechanism. so if you got for this, don't hold your breath for the future.

Reference: On Record/Class/Type Helpers.

Update: In XE4, a built-in helper class for integers, TIntegerHelper, has a method ToDouble.


Using RTTI it can be solved like this with built in language elements:

Format('Theoretical peak scaling %6.2f', 
  [TValue.From<Integer>(ThreadCount).AsExtended])

Just FTR, a benchmark shows that Double(Variant(i)) and inlined helper i.AsFloat are comparable, while TValue.From<Integer>(i).AsExtended is 200+ times slower.

like image 23
LU RD Avatar answered Oct 05 '22 23:10

LU RD


It's academic and I'd use a function or * 1.0 but this works

Format('Theoretical peak scaling %6.2f', [Double(Variant(ThreadCount))])
like image 33
bummi Avatar answered Oct 06 '22 00:10

bummi