use warnings; use strict; 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; # check the maxmum number of digits after the decimal point my $maxlen = max map { length( (split /\./,$_,2)[1]//'' ) } @array; # build the set my $set = Set::IntSpan->new( [ pairmap { [$a,$b] } map { my @x = split /\./, $_, 2; sprintf "%d%0*d", $x[0], $maxlen, $x[1]//0 } @array ] ); # normalize the input die "Input too wide" unless $input=~/\A\d+(\.\d{1,$maxlen})?\z/; my $innorm = do { my @x = split /\./, $input, 2; sprintf "%d%0*d", $x[0], $maxlen, $x[1]//0 }; # lookup if ( defined( my $ord = $set->span_ord( $innorm ) ) ) { my ($x,$y) = @array[ $ord*2, $ord*2+1 ]; print "found $input in span $x-$y\n"; } else { warn "did not find $input in any of the spans\n" } #### 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" }