Re: Why am I losing accuracy?
by haukex (Archbishop) on Jan 05, 2020 at 19:34 UTC
|
See the Math::BigInt docs in regards to its div_scale parameter: "This is the accuracy used when neither accuracy nor precision is set explicitly. It is used when a computation might otherwise attempt to return an infinite number of digits." The default value is 40, which is what you're seeing there.
You can either pass an accuracy to the bdiv method explicitly, for example: $digest = $digest->bdiv(64, 1000)->as_int;, or perhaps do this instead: use Math::BigRat; Math::BigRat->new($digest, 64)->as_int;, both of these result in your desired answer. (There are probably one or two other methods but these are the first I've thought of.)
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
Re: Why am I losing accuracy?
by bliako (Monsignor) on Jan 07, 2020 at 12:33 UTC
|
Why not keep it simple and use Math::BigInt or Math::BigFloat only for those variables who need it? (and not for ALL, e.g. loop variable $i)?
In fact, ikegami points that all you are doing is right shifts. So, probably you need BigInt (or a simple substr!). Sorry this is not what was suggested, I misunderstood that the default base for brsft() is 2, so it is not a right shift on base 10, i.e. $digest /= 64
bw, bliako
| [reply] [d/l] [select] |
|
use bigint (a => 80);
The final code actually does division by numbers other than 64, so I can't just use shift. :)
I am curious about how to assign Math::BigInt or Math::BigFloat (or bignum or bigint) only for the variables that need it. Can you enlighten me on how to do that? Thanks, again. | [reply] [d/l] |
|
I am curious about how to assign Math::BigInt or Math::BigFloat (or bignum or bigint) only for the variables that need it. Can you enlighten me on how to do that?
In that case don't use bignum;, instead use Math::BigInt; and/or use Math::BigFloat;, and then create the objects explicitly, as in my $i = Math::BigInt->new(1);. If you're done with the calculations and don't want them to be objects anymore, you can stringify them, e.g. $i = "$1"; - don't use them as numbers or you'll loose the accuracy.
| [reply] [d/l] [select] |
|
# for https://perlmonks.org/?node_id=11110997
# by bliako, 08/01/2020
use strict;
use warnings;
use Math::BigInt;
use Digest::SHA qw(sha256_hex);
for(my $i=1;$i<=10;$i++){
# the sha as a hex string (no '0x' prepended)
my $hexstr = sha256_hex($i);
# to create a bigint from a hex string we need to prepend '0x' to
+it
my $digest = Math::BigInt->new('0x'.$hexstr);
# specify accuracy and precision
$digest->accuracy(80);
$digest->precision(1);
# operate
print "$i $digest\n";
$digest /= 64;
print "$i $digest\n";
}
1 48635463943209834798109814161294753926839975257569795305637098542720
+658922320
1 75992912411265366872046584627023053010687461339952805165057966473001
+0295660
2 96094161643976066833367867971426158458230048495430276217795328666133
+331159860
2 15014712756871260442713729370535337259098445077410980659030520104083
+33299370
3 35293215426786447154857697798367884701614677727176325092965345248689
+205321680
3 55145649104353823679465152809949819846272933948713007957758351951076
+8833150
4 33984360982413536682390860969296307922929415152052354251133793603654
+468157320
4 53100564035021151066235720264525481129577211175081803517396552505710
+1064960
5 10818240655469999731486825095773005325907358940236581977057259273658
+4172823450
5 16903501024171874580448164212145320821730248344119659339151967615091
+27700370
6 10492023800686533720501340709024820017001830686534338836405100876796
+5015414400
6 16393787188572708938283344857851281276565360447709904431882970119994
+53365850
7 54734117258892461880478870895348100103198302433611928089023761078319
+507514450
7 85522058217019471688248235773981406411247347552518637639099626684874
+2304910
8 20075373234943686845167158285967784892467090849631486320124245130906
+619831460
8 31367770679599510695573684821824663894479829452549197375194133017041
+5934870
9 11463511883541201508393500803711559652562721115888819482889049505863
+143503290
9 17911737318033127356864845005799311957129251743576280442014139852911
+1617240
10 3359281535163583886622750554468341756416232122807515421831543601247
+6449103320
10 5248877398693099822848047741356783994400362691886742846611786876949
+44517240
Still, I would like to find out what's going on in that loop and gets stuck to 10 !!!!
bw, bliako | [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
Re: Why am I losing accuracy?
by ForgotPasswordAgain (Priest) on Jan 05, 2020 at 19:31 UTC
|
| [reply] |
|
#!/usr/bin/perl -w
use strict;
use bignum;
use Digest::SHA qw(sha256_hex);
# a small expansion on the previous code block
for (my $i = 1; $i <= 9; $i++)
{
my $digest = hex(sha256_hex($i));
print "$i $digest\n";
$digest /= 64;
print "$i $digest\n";
}
1 48635463943209834798109814161294753926839975257569795305637098542720
+658922315
1 75992912411265366872046584627023053010690000000000000000000000000000
+0000000
2 96094161643976066833367867971426158458230048495430276217795328666133
+331159861
2 15014712756871260442713729370535337259100000000000000000000000000000
+00000000
3 35293215426786447154857697798367884701614677727176325092965345248689
+205321678
3 55145649104353823679465152809949819846270000000000000000000000000000
+0000000
4 33984360982413536682390860969296307922929415152052354251133793603654
+468157322
4 53100564035021151066235720264525481129580000000000000000000000000000
+0000000
5 10818240655469999731486825095773005325907358940236581977057259273658
+4172823453
5 16903501024171874580448164212145320821730000000000000000000000000000
+00000000
6 10492023800686533720501340709024820017001830686534338836405100876796
+5015414403
6 16393787188572708938283344857851281276570000000000000000000000000000
+00000000
7 54734117258892461880478870895348100103198302433611928089023761078319
+507514449
7 85522058217019471688248235773981406411250000000000000000000000000000
+0000000
8 20075373234943686845167158285967784892467090849631486320124245130906
+619831459
8 31367770679599510695573684821824663894480000000000000000000000000000
+0000000
9 11463511883541201508393500803711559652562721115888819482889049505863
+143503287
9 17911737318033127356864845005799311957130000000000000000000000000000
+0000000
I start getting incorrect mathematical calculations here.
#!/usr/bin/perl -w
use strict;
# changed only this line
use bignum (p => 1);
use Digest::SHA qw(sha256_hex);
for (my $i = 1; $i <= 9; $i++)
{
my $digest = hex(sha256_hex($i));
print "$i $digest\n";
$digest /= 64;
print "$i $digest\n";
}
1 48635463943209834798109814161294753926839975257569795305637098542720
+658922315
1 81059106572016391330183023602157923211399958762616325509395164237867
+7648705
2 96094161643976066833367867971426158458230048495430276217795328666133
+331159861
2 16015693607329344472227977995237693076371674749238379369632554777688
+88852664
3 35293215426786447154857697798367884701614677727176325092965345248689
+205321678
3 58822025711310745258096162997279807836024462878627208488275575414482
+0088695
4 33984360982413536682390860969296307922929415152052354251133793603654
+468157322
4 56640601637355894470651434948827179871549025253420590418556322672757
+4469289
5 10818240655469999731486825095773005325907358940236581977057259273658
+4172823453
5 18030401092449999552478041826288342209845598233727636628428765456097
+36213724
6 10492023800686533720501340709024820017001830686534338836405100876796
+5015414403
6 17486706334477556200835567848374700028336384477557231394008501461327
+50256907
7 54734117258892461880478870895348100103198302433611928089023761078319
+507514449
7 91223528764820769800798118158913500171997170722686546815039601797199
+1791907
8 20075373234943686845167158285967784892467090849631486320124245130906
+619831459
8 33458955391572811408611930476612974820778484749385810533540408551511
+0330524
9 11463511883541201508393500803711559652562721115888819482889049505863
+143503287
9 19105853139235335847322501339519266087604535193148032471481749176438
+5725055
And here, things have really gone off of the rails.
#!/usr/bin/perl -w
use strict;
use bignum (p => 1);
use Digest::SHA qw(sha256_hex);
# here, I change 9 to 10
for (my $i = 1; $i <= 10; $i++)
{
my $digest = hex(sha256_hex($i));
print "$i $digest\n";
$digest /= 64;
print "$i $digest\n";
}
1 48635463943209834798109814161294753926839975257569795305637098542720
+658922315
1 81059106572016391330183023602157923211399958762616325509395164237867
+7648705
2 96094161643976066833367867971426158458230048495430276217795328666133
+331159861
2 16015693607329344472227977995237693076371674749238379369632554777688
+88852664
3 35293215426786447154857697798367884701614677727176325092965345248689
+205321678
3 58822025711310745258096162997279807836024462878627208488275575414482
+0088695
4 33984360982413536682390860969296307922929415152052354251133793603654
+468157322
4 56640601637355894470651434948827179871549025253420590418556322672757
+4469289
5 10818240655469999731486825095773005325907358940236581977057259273658
+4172823453
5 18030401092449999552478041826288342209845598233727636628428765456097
+36213724
6 10492023800686533720501340709024820017001830686534338836405100876796
+5015414403
6 17486706334477556200835567848374700028336384477557231394008501461327
+50256907
7 54734117258892461880478870895348100103198302433611928089023761078319
+507514449
7 91223528764820769800798118158913500171997170722686546815039601797199
+1791907
8 20075373234943686845167158285967784892467090849631486320124245130906
+619831459
8 33458955391572811408611930476612974820778484749385810533540408551511
+0330524
9 11463511883541201508393500803711559652562721115888819482889049505863
+143503287
9 19105853139235335847322501339519266087604535193148032471481749176438
+5725055
10 3359281535163583886622750554468341756416232122807515421831543601247
+6449103317
10 5598802558605973144371250924113902927360386871345859036385906002079
+40818389
10 3359281535163583886622750554468341756416232122807515421831543601247
+6449103317
10 5598802558605973144371250924113902927360386871345859036385906002079
+40818389
10 3359281535163583886622750554468341756416232122807515421831543601247
+6449103317
10 5598802558605973144371250924113902927360386871345859036385906002079
+40818389
[repeats indefinitely]
| [reply] [d/l] [select] |
|
I am definitely into things I don't understand here
I, too, don't know why it repeats indefinitely, but I can confirm that I see the same behaviour.
If you want something that DWIMs nicely, and works quickly and reliably, I would suggest using either Math::GMPz or Math::GMP.
Either will do, though they both require the GMP C library:
#!/usr/bin/perl -w
use strict;
use Math::GMPz;
# use Math::GMP;
use Digest::SHA qw(sha256_hex);
for (my $i = 1; $i <= 10; $i++) {
my $digest = Math::GMPz->new(sha256_hex($i), 16);
# my $digest = Math::GMP-> new(sha256_hex($i), 16);
print "$i $digest\n";
$digest /= 64;
print "$i $digest\n";
}
Output is:
1 48635463943209834798109814161294753926839975257569795305637098542720
+658922315
1 75992912411265366872046584627023053010687461339952805165057966473001
+0295661
2 96094161643976066833367867971426158458230048495430276217795328666133
+331159861
2 15014712756871260442713729370535337259098445077410980659030520104083
+33299372
3 35293215426786447154857697798367884701614677727176325092965345248689
+205321678
3 55145649104353823679465152809949819846272933948713007957758351951076
+8833151
4 33984360982413536682390860969296307922929415152052354251133793603654
+468157322
4 53100564035021151066235720264525481129577211175081803517396552505710
+1064958
5 10818240655469999731486825095773005325907358940236581977057259273658
+4172823453
5 16903501024171874580448164212145320821730248344119659339151967615091
+27700366
6 10492023800686533720501340709024820017001830686534338836405100876796
+5015414403
6 16393787188572708938283344857851281276565360447709904431882970119994
+53365850
7 54734117258892461880478870895348100103198302433611928089023761078319
+507514449
7 85522058217019471688248235773981406411247347552518637639099626684874
+2304913
8 20075373234943686845167158285967784892467090849631486320124245130906
+619831459
8 31367770679599510695573684821824663894479829452549197375194133017041
+5934866
9 11463511883541201508393500803711559652562721115888819482889049505863
+143503287
9 17911737318033127356864845005799311957129251743576280442014139852911
+1617238
10 3359281535163583886622750554468341756416232122807515421831543601247
+6449103317
10 5248877398693099822848047741356783994400362691886742846611786876949
+44517239
Cheers, Rob | [reply] [d/l] [select] |