Home > Blockchain >  How can I convert an integer to a float value in Perl?
How can I convert an integer to a float value in Perl?

Time:10-29

I searched for a built in function to convert an integer to float type, but there isn't any. I want to convert a number 1000 into 1000.0

CodePudding user response:

For actual maths, there is no need to convert numbers. Perl doesn't make a distinction between integers and floats (it actually does under the hood, but that isn't relevant).

If you want to output a number with decimals, you can use sprintf or printf respectively.

The %f conversion is what you want here. You can tell it to have decimals after the comma.

printf '%.1f', 1000; # will print 1000.0

This will respect your locale and use the correct sign for the comma.

CodePudding user response:

If you're actually asking how to convert a float into a decimal string representation with decimal places, then you can use printf/sprintf.

For example, the following prints $x with one decimal place, whether it's a number stored as an integer or float.

my $x = 1000;
printf "%.1f", $x;   # 1000.0

But if you really do want to convert to a float as you asked, there is no builtin function to do this.

Perl will automatically convert a scalar to a floating point number when needed (e.g. when multiplying an integer by 0.1), so there's normally no need for something this. In fact, there's no builtin mechanism to do it.

While 1.0 creates a float (NOK), you can't even get one by multiplying by 1.0 (using * 0.1 or *= 0.1).

$ perl -MDevel::Peek -e'
   my $x = 1000;      Dump( $x );
   my $y = 1.0;       Dump( $y );
   my $z = $x * $y;   Dump( $z );
'
SV = IV(0x55efe5c37e58) at 0x55efe5c37e68
  REFCNT = 1
  FLAGS = (IOK,pIOK)      <-- Signed integer
  IV = 1000
SV = NV(0x55efe5c37e98) at 0x55efe5c37eb0
  REFCNT = 1
  FLAGS = (NOK,pNOK)      <-- Floating point number
  NV = 1
SV = IV(0x55efe5c37ff0) at 0x55efe5c38000
  REFCNT = 1
  FLAGS = (IOK,pIOK)      <-- Signed integer
  IV = 1000

It's simply not something you should want to do.

The issue is that some interfaces impart meaning on how a number is stored. For example, a JSON serializer might serialize numbers stored as integers differently than numbers stored as floats. This could be considered a bug.

Bug or not, it doesn't change the fact that you need the requested conversion. It can be done using the Perl API.

use Inline C => <<'__EOS__';

   SV* SvNV_force( SV* sv ) {
      SvREFCNT_inc( sv );
      sv_setnv( sv, SvNV( sv ) );
      return sv;
   }

__EOS__

use Devel::Peek qw( Dump );

my $x = 1000;       Dump( $x );
SvNV_force( $x );   Dump( $x );
SV = IV(0x55a354e92508) at 0x55a354e92518
  REFCNT = 1
  FLAGS = (IOK,pIOK)      <-- Signed integer
  IV = 1000
SV = PVNV(0x55a354e611a0) at 0x55a354e92518
  REFCNT = 1
  FLAGS = (NOK,pNOK)      <-- Floating point number
  IV = 1000
  NV = 1000
  PV = 0
  •  Tags:  
  • perl
  • Related