### Scientific Notation Throws Off Results.

by Elijah (Hermit)
 on Jan 13, 2004 at 23:29 UTC Need Help??
Elijah has asked for the wisdom of the Perl Monks concerning the following question:

I have a program that converts ATM cells per second to IP bandwidth but when the peak cell rate reaches a point where the answer starts to be displayed in scientific notation the formatting I have gets thrown off.

```sub convert {
my (\$len1, \$type);
if (\$choice eq "Cells to Bits") {
if (\$pcr && \$cell_size) {
\$answer = \$pcr * \$cell_size * 8;
print \$len1,"\n";
if ((\$len1 < 4) || (\$len1 > 15)) {
\$type = "b/s";
}elsif ((\$len1 >= 4) && (\$len1 <= 6)) {
\$type = "Kb/s";
}elsif ((\$len1 >= 7) && (\$len1 <= 9)) {
\$type = "Mb/s";
}else{
\$type = "Gb/s";
my \$count = 1;
while (\$count < 10) {
\$count++;
}
}
\$status = "Conversion Successfull!";
}else{
\$status = "Error: required field missing!";
}
}elsif (\$choice eq "Bits to Cells") {
if (\$bps && \$cell_size2) {
\$answer = \$bps / 8 / \$cell_size2;
\$status = "Conversion Successfull!";
}else{
\$status = "Error: required field missing!";
}
}else{
\$status = "Error: required field missing!";
}
}

As you can see I use length to check for number of digits and format accordingly. Well once the length of the answer gets too long perl automatically shortens it by using Scientific notation. My question is is there any way to disable perl from returning calculated results in scientific notation or any other way to stop this from happening?

Replies are listed 'Best First'.
Re: Scientific Notation Throws Off Results.
by Zaxo (Archbishop) on Jan 13, 2004 at 23:40 UTC

You're pushing the limit of perl integers. Either build perl for 64-bit integers or else use Math::BigInt;
If speed is a problem, use Math::BigInt lib => GMP;

After Compline,
Zaxo

Re: Scientific Notation Throws Off Results.
by ysth (Canon) on Jan 14, 2004 at 00:12 UTC
I assume what's giving you trouble is the:
```\$answer = \$pcr * \$cell_size * 8;
part (which computes a number and then calculates the length of its stringified form). Perl by default uses something like \$str = sprintf("%.15g",\$num) to stringify floating point numbers (where the %g format chooses whether to look like %e or %f). You can do it manually instead, never using the scientfic notation, with:
```\$answer = sprintf "%.0f", \$answer;
You might be better off checking for numberic ranges; for instance (untested):
```if (\$answer >= 1000 && \$answer < 1000000) {
} else ...
or a version that incorporates rounding instead of truncation:
```if (\$answer >= 999.5 && \$answer < 999500) {
} else ...
Re: Scientific Notation Throws Off Results.
by bl0rf (Pilgrim) on Jan 14, 2004 at 00:22 UTC
Get rid of \$len and use the numbers themselves:
```  if ((\$answer < 1000) || (\$len1 > 1e14)) {
\$type = "b/s";
\$type = "Kb/s";
}elsif ((\$len1 > 1e6) && (\$len1 <= 1e9)) {
\$type = "Mb/s";
}else{
Just do a numeric check on \$answer instead of tinkering with \$length. By the way, 1e6 means: one multiplied by ten to the six( ten with six zeros).

Re: Scientific Notation Throws Off Results.
by NetWallah (Canon) on Jan 14, 2004 at 01:53 UTC
Here is some code I use to display Kilo, Meg, Gig etc .. You could probably use this directly ..
```sub format_kilo  # Kilo, mega and gig
{
my \$number = shift;
my \$fixwidth = shift;
my \$suffix = " ";

if (\$number > 0x40000000)
{
\$number /= 0x40000000;
\$suffix = 'G';
}
elsif (\$number > 0x100000)
{
\$number /= 0x100000;
\$suffix = 'M';
}
elsif (\$number > 0x400)
{
\$number /= 0x400;
\$suffix = 'K';
}

# Split integer and decimal parts of the number and add commas
my \$integer = int(\$number);

\$fixwidth and \$integer =  ' ' x (\$fixwidth - length(\$integer) - le
+ngth(\$suffix)) . \$integer;

# Combine it all back together and return it.
return \$integer.\$suffix;
}

##### Calling sequence ###
my (\$filename, \$filebytes);
\$filename = "Your file name here....";
\$filebytes = -s \$filename;

print "Opening File=\$filename; (".
format_kilo(\$filebytes)  . " [=\$filebytes] bytes)\n";

"When you are faced with a dilemma, might as well make dilemmanade. "
Re: Scientific Notation Throws Off Results.
by Abigail-II (Bishop) on Jan 13, 2004 at 23:43 UTC
Well, I can see where you are using length, but your code fragment offers no indication at all which value Perl is shortening to scientific notation. Are we talking floats here? Integers? Which value are you printing, what are you getting, and what do you want to get?

Abigail

Sorry, here is the full code so you might have a better idea of what goes where. It is a gui app written in Tk.

```#!/usr/local/bin/perl -w

#perl2exe_include Tk;
#perl2exe_include Tk::Photo;
#perl2exe_include strict;

use Tk;
use Tk::Photo;
use strict;

###########################################
###########################################
##                                       ##
## This script is a graphical interface  ##
## that allows a user to easily convert  ##
## IP bandwidth into ATM PCR.            ##
## PCR = (Peak Cell rate)                ##
##                                       ##
###########################################
###########################################

our(\$choice, \$cb, \$pcr, \$bps, \$status, \$answer, \$cell_size, \$cell_size
+2);

my \$window = MainWindow->new;
\$window->title("ip2atm");

my \$frame_space = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame  = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame_space2 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame2 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame_space3 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame3 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame4 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame_space5 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame5 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame6 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame_space7 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame7 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame_space8 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame8 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame9 = \$window->Frame->pack(-side=>'top', -fill=>'x');
my \$frame10 = \$window->Frame->pack(-side=>'top', -fill=>'x');

\$frame_space->Label()->pack(-fill=>'x');

\$frame->Label(-text=>"Choose Conversion Type")->pack(-side=>'top', -an
+chor=>'n');

\$frame->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

\$frame->Button(-text=>"Cells to Bits", -command=>\&cb)->
pack(-side=>'left', -anchor=>'w', -fill=>'none');

\$frame->Label(-text=>"  ")->pack(-side=>'right', -anchor=>'e');

\$frame->Button(-text=>"Bits to Cells", -command=>\&bc)->
pack(-side=>'right', -anchor=>'e', -fill=>'none');

\$frame_space2->Label()->pack(-fill=>'x');

\$frame2->Label(-text=>"Conversion Type Being Used")->pack(-side=>'top'
+, -anchor=>'n');

\$frame2->Entry(-textvariable=>\\$choice)->
pack(-side=>'bottom', -anchor=>'n', -fill=>'none');

\$frame_space3->Label()->pack(-fill=>'x');

\$frame3->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

\$frame3->Label(-text=>"Enter Peak Cell Rate")->pack(-side=>'left', -an
+chor=>'w');

\$frame3->Label(-text=>"  ")->pack(-side=>'right', -anchor=>'e');

\$frame3->Label(-text=>"Enter Bits Per Second")->pack(-side=>'right', -
+anchor=>'e');

\$frame4->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

\$frame4->Entry(-textvariable=>\\$pcr)->
pack(-side=>'left', -anchor=>'w', -fill=>'none');

\$frame4->Label(-text=>"   ")->pack(-side=>'left', -anchor=>'w');

\$frame4->Label(-text=>"  ")->pack(-side=>'right', -anchor=>'e');

\$frame4->Entry(-textvariable=>\\$bps)->
pack(-side=>'right', -anchor=>'e', -fill=>'none');

\$frame_space5->Label()->pack(-fill=>'x');

\$frame5->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

\$frame5->Label(-text=>"Enter Cell Size")->pack(-side=>'left', -anchor=
+>'w');

\$frame5->Label(-text=>"  ")->pack(-side=>'right', -anchor=>'e');

\$frame5->Label(-text=>"Enter Cell Size")->pack(-side=>'right', -anchor
+=>'e');

\$frame6->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

\$frame6->Entry(-textvariable=>\\$cell_size)->
pack(-side=>'left', -anchor=>'w', -fill=>'none');

\$frame6->Label(-text=>"   ")->pack(-side=>'left', -anchor=>'w');

\$frame6->Label(-text=>"  ")->pack(-side=>'right', -anchor=>'e');

\$frame6->Entry(-textvariable=>\\$cell_size2)->
pack(-side=>'right', -anchor=>'e', -fill=>'none');

\$frame_space7->Label()->pack(-fill=>'x');

\$frame7->Button(-text=>" Convert ", -command=>\&convert)->
pack(-side=>'top', -anchor=>'n');

\$frame_space8->Label()->pack(-fill=>'x');

\$frame9->Label(-text=>"  ")->pack(-side=>'left', -anchor=>'w');

pack(-side=>'top', -anchor=>'n', -fill=>'none');

\$frame10->Button(-text=>" Exit ", -command=>sub{exit;})->
pack(-side=>'bottom', -anchor=>'e');

\$window->Label(-textvariable=>\\$status, -relief=>'ridge')->
pack(-side=>'bottom', -fill=>'x');

if (-e "converter.gif") {
\$window->Photo('image', -file=>"converter.gif");
\$window->Label(-image=>'image')->pack(-side=>'bottom');
}

\$status = "Written by: Me";

MainLoop;

sub cb {
\$choice     = "Cells to Bits";
\$bps        = "N/A";
\$cell_size2 = "N/A";
\$pcr        = "";
\$cell_size  = "";
}

sub bc {
\$choice     = "Bits to Cells";
\$pcr        = "N/A";
\$cell_size  = "N/A";
\$bps        = "";
\$cell_size2 = "";
}

sub convert {
my (\$len1, \$type);
if (\$choice eq "Cells to Bits") {
if (\$pcr && \$cell_size) {
\$answer = \$pcr * \$cell_size * 8;
print \$len1,"\n";
if ((\$len1 < 4) || (\$len1 > 15)) {
\$type = "b/s";
}elsif ((\$len1 >= 4) && (\$len1 <= 6)) {
\$type = "Kb/s";
}elsif ((\$len1 >= 7) && (\$len1 <= 9)) {
\$type = "Mb/s";
}else{
\$type = "Gb/s";
foreach (my \$count=1; \$count<10; \$count++) {
}
}
\$status = "Conversion Successfull!";
}else{
\$status = "Error: required field missing!";
}
}elsif (\$choice eq "Bits to Cells") {
if (\$bps && \$cell_size2) {
\$answer = \$bps / 8 / \$cell_size2;
\$status = "Conversion Successfull!";
}else{
\$status = "Error: required field missing!";
}
}else{
\$status = "Error: required field missing!";
}
}
I know that after 15 digits (yes integers) that the format changes to scientific notation therefore I have coded that into my script but after I think

Here is a debugger output I have going to the command prompt to check the value of the 2 variables (\$len1 and \$answer) and you cans ee where the length jumps back down and screws me.

```5
41976
6
423576
7
4239576
8
42399576
9
423999576
10
4239999576
11
42399999576
12
423999999576
13
4239999999576
14
42399999999576
15
423999999999576
21
4.23999999999958e+015
21
4.23999999999996e+016
9
4.24e+017

The first number (as you can see by the code) is the value of the length in digits of the answer and the second (longer number) is the actual answer.

No doubt very interesting, but I'm not going to try to grok a program several pages long.

Try posting a short program that exhibits the unwanted behaviour.

Abigail

Re: Scientific Notation Throws Off Results.
by fruiture (Curate) on Jan 14, 2004 at 15:53 UTC

bl0rf said it: don't stringify things that you don't actually need as strings. The "number of digits" needs no stringification, it's a logarithm:

```sub number_of_digits {
my \$number = shift;
my \$base = shift || 10;

1 + int( log(\$number) / log(\$base) )
}
--
http://fruiture.de

Create A New User
Node Status?
node history
Node Type: perlquestion [id://321139]
Approved by dorko
Front-paged by broquaint
help
Chatterbox?
 [marto]: Good morning all

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2018-04-21 06:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (81 votes). Check out past polls.

Notices?