⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calc.pm

📁 网页留言本,比一般的留言簿管用
💻 PM
📖 第 1 页 / 共 4 页
字号:
       {       $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $MBASE;       };    return $xv;    }  # shortcut for result == 0  if ( ((@$xv == 1) && ($xv->[0] == 0)) ||       ((@$yv == 1) && ($yv->[0] == 0)) )    {    @$xv = (0);    return $xv;    }  # since multiplying $x with $x fails, make copy in this case  $yv = [@$xv] if $xv == $yv;	# same references?  if ($LEN_CONVERT != 0)    {    $c->_to_small($xv); $c->_to_small($yv);    }  my @prod = (); my ($prod,$car,$cty,$xi,$yi);  for $xi (@$xv)    {    $car = 0; $cty = 0;    # slow variant#    for $yi (@$yv)#      {#      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;#      $prod[$cty++] =#       $prod - ($car = int($prod * RBASE)) * $MBASE;  # see USE_MUL#      }#    $prod[$cty] += $car if $car; # need really to check for 0?#    $xi = shift @prod;    # faster variant    # looping through this if $xi == 0 is silly - so optimize it away!    $xi = (shift @prod || 0), next if $xi == 0;    for $yi (@$yv)      {      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;##     this is actually a tad slower##        $prod = $prod[$cty]; $prod += ($car + $xi * $yi);	# no ||0 here      $prod[$cty++] =       $prod - ($car = int($prod * $RBASE)) * $MBASE;  # see USE_MUL      }    $prod[$cty] += $car if $car; # need really to check for 0?    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy    }  push @$xv, @prod;  if ($LEN_CONVERT != 0)    {    $c->_to_large($yv);    $c->_to_large($xv);    }  else    {    __strip_zeros($xv);    }  $xv;  }                                                                             sub _mul_use_div  {  # (ref to int_num_array, ref to int_num_array)  # multiply two numbers in internal representation  # modifies first arg, second need not be different from first  my ($c,$xv,$yv) = @_;   # shortcut for two very short numbers (improved by Nathan Zook)  # works also if xv and yv are the same reference  if ((@$xv == 1) && (@$yv == 1))    {    if (($xv->[0] *= $yv->[0]) >= $MBASE)        {        $xv->[0] =            $xv->[0] - ($xv->[1] = int($xv->[0] / $MBASE)) * $MBASE;        };    return $xv;    }  # shortcut for result == 0  if ( ((@$xv == 1) && ($xv->[0] == 0)) ||       ((@$yv == 1) && ($yv->[0] == 0)) )    {    @$xv = (0);    return $xv;    }   # since multiplying $x with $x fails, make copy in this case  $yv = [@$xv] if $xv == $yv;	# same references?  if ($LEN_CONVERT != 0)    {    $c->_to_small($xv); $c->_to_small($yv);    }    my @prod = (); my ($prod,$car,$cty,$xi,$yi);  for $xi (@$xv)    {    $car = 0; $cty = 0;    # looping through this if $xi == 0 is silly - so optimize it away!    $xi = (shift @prod || 0), next if $xi == 0;    for $yi (@$yv)      {      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;      $prod[$cty++] =       $prod - ($car = int($prod / $MBASE)) * $MBASE;      }    $prod[$cty] += $car if $car; # need really to check for 0?    $xi = shift @prod || 0;	# || 0 makes v5.005_3 happy    }  push @$xv, @prod;  if ($LEN_CONVERT != 0)    {    $c->_to_large($yv);    $c->_to_large($xv);    }  else    {    __strip_zeros($xv);    }  $xv;  }                                                                             sub _div_use_mul  {  # ref to array, ref to array, modify first array and return remainder if   # in list context  my ($c,$x,$yorg) = @_;  if (@$x == 1 && @$yorg == 1)    {    # shortcut, $yorg and $x are two small numbers    if (wantarray)      {      my $r = [ $x->[0] % $yorg->[0] ];      $x->[0] = int($x->[0] / $yorg->[0]);      return ($x,$r);       }    else      {      $x->[0] = int($x->[0] / $yorg->[0]);      return $x;       }    }  if (@$yorg == 1)    {    my $rem;    $rem = _mod($c,[ @$x ],$yorg) if wantarray;    # shortcut, $y is < $BASE    my $j = scalar @$x; my $r = 0;     my $y = $yorg->[0]; my $b;    while ($j-- > 0)      {      $b = $r * $MBASE + $x->[$j];      $x->[$j] = int($b/$y);      $r = $b % $y;      }    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero     return ($x,$rem) if wantarray;    return $x;    }  my $y = [ @$yorg ];				# always make copy to preserve  if ($LEN_CONVERT != 0)    {    $c->_to_small($x); $c->_to_small($y);    }  my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);  $car = $bar = $prd = 0;  if (($dd = int($MBASE/($y->[-1]+1))) != 1)     {    for $xi (@$x)       {      $xi = $xi * $dd + $car;      $xi -= ($car = int($xi * $RBASE)) * $MBASE;	# see USE_MUL      }    push(@$x, $car); $car = 0;    for $yi (@$y)       {      $yi = $yi * $dd + $car;      $yi -= ($car = int($yi * $RBASE)) * $MBASE;	# see USE_MUL      }    }  else     {    push(@$x, 0);    }  @q = (); ($v2,$v1) = @$y[-2,-1];  $v2 = 0 unless $v2;  while ($#$x > $#$y)     {    ($u2,$u1,$u0) = @$x[-3..-1];    $u2 = 0 unless $u2;    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"    # if $v1 == 0;     $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));    --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);    if ($q)      {      ($car, $bar) = (0,0);      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)         {        $prd = $q * $y->[$yi] + $car;        $prd -= ($car = int($prd * $RBASE)) * $MBASE;	# see USE_MUL	$x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));	}      if ($x->[-1] < $car + $bar)         {        $car = 0; --$q;	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)           {	  $x->[$xi] -= $MBASE	   if ($car = (($x->[$xi] += $y->[$yi] + $car) > $MBASE));	  }	}         }      pop(@$x); unshift(@q, $q);    }  if (wantarray)     {    @d = ();    if ($dd != 1)        {      $car = 0;       for $xi (reverse @$x)         {        $prd = $car * $MBASE + $xi;        $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL        unshift(@d, $tmp);        }      }    else       {      @d = @$x;      }    @$x = @q;    my $d = \@d;     if ($LEN_CONVERT != 0)      {      $c->_to_large($x); $c->_to_large($d);      }    else      {      __strip_zeros($x);      __strip_zeros($d);      }    return ($x,$d);    }  @$x = @q;  if ($LEN_CONVERT != 0)    {    $c->_to_large($x);    }  else    {    __strip_zeros($x);    }  $x;  }sub _div_use_div  {  # ref to array, ref to array, modify first array and return remainder if   # in list context  my ($c,$x,$yorg) = @_;  if (@$x == 1 && @$yorg == 1)    {    # shortcut, $yorg and $x are two small numbers    if (wantarray)      {      my $r = [ $x->[0] % $yorg->[0] ];      $x->[0] = int($x->[0] / $yorg->[0]);      return ($x,$r);       }    else      {      $x->[0] = int($x->[0] / $yorg->[0]);      return $x;       }    }  if (@$yorg == 1)    {    my $rem;    $rem = _mod($c,[ @$x ],$yorg) if wantarray;    # shortcut, $y is < $BASE    my $j = scalar @$x; my $r = 0;     my $y = $yorg->[0]; my $b;    while ($j-- > 0)      {      $b = $r * $MBASE + $x->[$j];      $x->[$j] = int($b/$y);      $r = $b % $y;      }    pop @$x if @$x > 1 && $x->[-1] == 0;	# splice up a leading zero     return ($x,$rem) if wantarray;    return $x;    }  my $y = [ @$yorg ];				# always make copy to preserve  if ($LEN_CONVERT != 0)    {    $c->_to_small($x); $c->_to_small($y);    }   my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);  $car = $bar = $prd = 0;  if (($dd = int($MBASE/($y->[-1]+1))) != 1)     {    for $xi (@$x)       {      $xi = $xi * $dd + $car;      $xi -= ($car = int($xi / $MBASE)) * $MBASE;      }    push(@$x, $car); $car = 0;    for $yi (@$y)       {      $yi = $yi * $dd + $car;      $yi -= ($car = int($yi / $MBASE)) * $MBASE;      }    }  else     {    push(@$x, 0);    }  @q = (); ($v2,$v1) = @$y[-2,-1];  $v2 = 0 unless $v2;  while ($#$x > $#$y)     {    ($u2,$u1,$u0) = @$x[-3..-1];    $u2 = 0 unless $u2;    #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"    # if $v1 == 0;     $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));    --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);    if ($q)      {      ($car, $bar) = (0,0);      for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)         {        $prd = $q * $y->[$yi] + $car;        $prd -= ($car = int($prd / $MBASE)) * $MBASE;	$x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));	}      if ($x->[-1] < $car + $bar)         {        $car = 0; --$q;	for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi)           {	  $x->[$xi] -= $MBASE	   if ($car = (($x->[$xi] += $y->[$yi] + $car) > $MBASE));	  }	}         }    pop(@$x); unshift(@q, $q);    }  if (wantarray)     {    @d = ();    if ($dd != 1)        {      $car = 0;       for $xi (reverse @$x)         {        $prd = $car * $MBASE + $xi;        $car = $prd - ($tmp = int($prd / $dd)) * $dd;        unshift(@d, $tmp);        }      }    else       {      @d = @$x;      }    @$x = @q;    my $d = \@d;     if ($LEN_CONVERT != 0)      {      $c->_to_large($x); $c->_to_large($d);      }    else      {      __strip_zeros($x);      __strip_zeros($d);      }    return ($x,$d);    }  @$x = @q;  if ($LEN_CONVERT != 0)    {    $c->_to_large($x);    }  else    {    __strip_zeros($x);    }  $x;  }############################################################################### testingsub _acmp  {  # internal absolute post-normalized compare (ignore signs)  # ref to array, ref to array, return <0, 0, >0  # arrays must have at least one entry; this is not checked for  my ($c,$cx,$cy) = @_;  # fast comp based on number of array elements (aka pseudo-length)  my $lxy = scalar @$cx - scalar @$cy;  return -1 if $lxy < 0;				# already differs, ret  return 1 if $lxy > 0;					# ditto  # now calculate length based on digits, not parts  # we need only the length of the last element, since both array have the  # same number of parts  $lxy = length(int($cx->[-1])) - length(int($cy->[-1]));  return -1 if $lxy < 0;  return 1 if $lxy > 0;  # hm, same lengths,  but same contents? So we need to check all parts:  my $a; my $j = scalar @$cx - 1;  # manual way (abort if unequal, good for early ne)  while ($j >= 0)    {    last if ($a = $cx->[$j] - $cy->[$j]); $j--;    }  return 1 if $a > 0;  return -1 if $a < 0;  0;						# numbers are equal  }sub _len  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -