use warnings; use strict; use Data::Dump; use List::Util qw/max pairmap/; use Set::IntSpan; my @array = (1.1,1.4,5.33,6.1,7.23,7.133,10,11); my $input = 7.25; # "normalize" the input (could also use fixed @maxlen) my @maxlen = map { my $x=$_; max map { length $$_[$x] } map { my @e=split /\./,$_,2; @e>1 ? \@e : [@e,0] } @array } 0,1; my $normalize = sub { my ($s) = @_; die "Invalid: $s" unless $s=~/\A\d{1,$maxlen[0]}(\.\d{1,$maxlen[1]})?\z/; my ($x,$y) = split /\./, $s, 2; 0+sprintf "%*d%0*d", $maxlen[0], $x, $maxlen[1], $y//0 }; my $denormalize = sub { my ($n) = @_; die "Too long: $n" if length($n)>$maxlen[0]+$maxlen[1]; my $y = 0+substr $n, -$maxlen[1], $maxlen[1], ''; return (0+($n||0)).($y?".$y":'') }; dd map { $normalize->($_) } @array; # Debug # => "(1001, 1004, 5033, 6001, 7023, 7133, 10000, 11000)" dd map { $denormalize->($normalize->($_)) } @array; # => "(1.1, 1.4, 5.33, 6.1, 7.23, 7.133, 10, 11)" $denormalize->($normalize->($_)) eq $_ or die "$_" for @array; # Test my $set = Set::IntSpan->new( [ pairmap { [$a,$b] } map { $normalize->($_) } @array ] ); print $set->run_list, "\n"; # Debug # => "1001-1004,5033-6001,7023-7133,10000-11000" if ( defined( my $ord = $set->span_ord( $normalize->($input) ) ) ) { my $span = ($set->spans)[$ord]; print "found $input in span ", join( '-', map { $denormalize->($_) } @$span ), "\n"; # => "found 7.25 in span 7.23-7.133" } else { warn "did not find $input in any of the spans\n" }