-1

all

I am Joshua.

Currently I am developing some kind of calculation logic in C#, .NET 4.7. And I am stuck for a couple of days when using ModPow from BigInteger class. Finally I compared with some other languages like Javascript and Python.

Here are the codes;

C#

var _a                      = BigInteger.Parse("-112504099738967919768410869814860903982619354592334385300478909977139427923361560492994684609769555842111970113942123739668771370088164545697837713491001933076595596664223176568695966455489156970812960564312137880189440762210023504737301351876623478203051273064143361985681097609967600291953777514093844982210010914333130253653115287655327635099624170100570446664200407152843331467876643789736619196583683418866514683967222986915221982722110686116114379750004515841618651243098835937383564483775550060041152863597757016771967904349656600797877149977649728258675384541203748747540152406727068415700988829908215424137984927266987257127615691501812286981137284264501640480312282004988469360705007547931588660449754580929985074021203105802730617855236140743357649842847802339153126105816742502906195190402079944900015779354117203169724787481860002766072928442884322075317745510521170465176626766316916518300959480576101945671060969719420147093892605449154540004740863401759952424765321581716947920578041839", NumberStyles.Number);
var _b                      = BigInteger.Parse("42710288472123706107732045980552936061105504205720832439400517546130482902053491661703847614802545363376415610740434485703528101945149576942291183712758802525948559100109353863348012045024391482754729786318228709846887076811626987986636873030977565323002665497040002349699696324754471341241246091133248712513", NumberStyles.Number);
var _c                      = BigInteger.Parse("5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807", NumberStyles.Number);
var _modPowRes              = BigInteger.ModPow(_a, _b, _c);
        
NumberFormatInfo _formatter = new NumberFormatInfo();
_formatter.NegativeSign     = "-";
string _stringRes           = _modPowRes.ToString("D", _formatter);
// -4025962189194561064516553363283375014525921961557175720338529077112971710311848366234203913802556580292548393361209331638020083844074732374616343653135077799402946400533385408838985464487221381056062706959966844828188406680815976045839849337092509291814967568127589935214307295687077940893465121894442245470126915769901660325457529592729859443914551917517655171549159468233372814554103351084536838316208603471169266662039167296594675085295938849603548128017384775032304908588861826301095512209694112961080272106412321025934327013828425487280677537982063915874200399589997896633613461631025068511458444974149152947749747984549594822000420708352393424384641432718686749229405669436317664008070112083271636922781745940251494349374415266883563753139424535520085753958356376469108498554786941521255255003415937460671624180845917463097501347690828778209895285876290213489273200505952380626734459377765095025966725691306820725825499

Javascript, I used jsbn library

var _a                      = new BigInteger("-112504099738967919768410869814860903982619354592334385300478909977139427923361560492994684609769555842111970113942123739668771370088164545697837713491001933076595596664223176568695966455489156970812960564312137880189440762210023504737301351876623478203051273064143361985681097609967600291953777514093844982210010914333130253653115287655327635099624170100570446664200407152843331467876643789736619196583683418866514683967222986915221982722110686116114379750004515841618651243098835937383564483775550060041152863597757016771967904349656600797877149977649728258675384541203748747540152406727068415700988829908215424137984927266987257127615691501812286981137284264501640480312282004988469360705007547931588660449754580929985074021203105802730617855236140743357649842847802339153126105816742502906195190402079944900015779354117203169724787481860002766072928442884322075317745510521170465176626766316916518300959480576101945671060969719420147093892605449154540004740863401759952424765321581716947920578041839", 10);
var _b                      = new BigInteger("42710288472123706107732045980552936061105504205720832439400517546130482902053491661703847614802545363376415610740434485703528101945149576942291183712758802525948559100109353863348012045024391482754729786318228709846887076811626987986636873030977565323002665497040002349699696324754471341241246091133248712513", 10);
var _c                      = new BigInteger("5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807", 10);
var _modPowRes              = _a.modPow(_b, _c);
var _stringRes              = _modPowRes.toString(10);
// 1783643806175396998275362602355826387650690265345724813364371805666764467579142495237890860674783000854825016824437046690023645956675737723594580834731857259761425187634662132104996180029411374011438919474589553364998222309255272614979511868027284402170465728908528297700102876189729595563926155962569604427283291749203673030343591516627038015511719927953742781126799972560120257074290771695973286302279629131295383214811291564651109155633319576684151577295199734593114604874743329126921653504771250132941337184148762999959335547394147714802188259839801355116944682610659081543579365393513921728510730572041617697936145453462119608425988630323921319186513104423344823774870759265115372373731593225388193828408607005773987710556891304121163609340263880054616842988101393815039937434342691332663137114581535172021453932283969024301846449291944006405969946744999443455011016318658938083030075774742259090377978078691693422518308

Python

_a          = -112504099738967919768410869814860903982619354592334385300478909977139427923361560492994684609769555842111970113942123739668771370088164545697837713491001933076595596664223176568695966455489156970812960564312137880189440762210023504737301351876623478203051273064143361985681097609967600291953777514093844982210010914333130253653115287655327635099624170100570446664200407152843331467876643789736619196583683418866514683967222986915221982722110686116114379750004515841618651243098835937383564483775550060041152863597757016771967904349656600797877149977649728258675384541203748747540152406727068415700988829908215424137984927266987257127615691501812286981137284264501640480312282004988469360705007547931588660449754580929985074021203105802730617855236140743357649842847802339153126105816742502906195190402079944900015779354117203169724787481860002766072928442884322075317745510521170465176626766316916518300959480576101945671060969719420147093892605449154540004740863401759952424765321581716947920578041839
_b          = 42710288472123706107732045980552936061105504205720832439400517546130482902053491661703847614802545363376415610740434485703528101945149576942291183712758802525948559100109353863348012045024391482754729786318228709846887076811626987986636873030977565323002665497040002349699696324754471341241246091133248712513
_c          = 5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807
_modPowRes  = pow(_a, _b, _c)
print(_modPowRes)
#1783643806175396998275362602355826387650690265345724813364371805666764467579142495237890860674783000854825016824437046690023645956675737723594580834731857259761425187634662132104996180029411374011438919474589553364998222309255272614979511868027284402170465728908528297700102876189729595563926155962569604427283291749203673030343591516627038015511719927953742781126799972560120257074290771695973286302279629131295383214811291564651109155633319576684151577295199734593114604874743329126921653504771250132941337184148762999959335547394147714802188259839801355116944682610659081543579365393513921728510730572041617697936145453462119608425988630323921319186513104423344823774870759265115372373731593225388193828408607005773987710556891304121163609340263880054616842988101393815039937434342691332663137114581535172021453932283969024301846449291944006405969946744999443455011016318658938083030075774742259090377978078691693422518308

As you can see, all the consant valus _a, _b and _c are the same. But only C# gives me the different result of ModPow. I have tried smaller numbers, then C# gives me the same result as other languages. I have tried to run my unit test project as x64, x86 and AnyCpu on platform target. But the result is the same. Can somebody explain why this is happening?

Joshua Son
  • 1,839
  • 6
  • 31
  • 51
  • [What's the difference? Remainder vs Modulus](https://learn.microsoft.com/en-us/archive/blogs/ericlippert/whats-the-difference-remainder-vs-modulus) => [Math from scratch, part eleven: integer division](https://ericlippert.com/2013/10/31/math-from-scratch-part-eleven-integer-division/) – Jimi Dec 03 '22 at 07:34
  • `var pyModulus = (_modPowRes % _c + _c) % _c;` – Jimi Dec 03 '22 at 07:46
  • Thanks. I will hve a read and take a note on your code. – Joshua Son Dec 03 '22 at 08:28

1 Answers1

1

Python and C# have different definitions of Mod. Python uses the mathematical definition of mod (the result is always a non-negative number) while C# returns a value with the same sign as you started with.

You'll notice that the difference between C#'s answer and Python's answer is precisely the modulus. In effect, both are returning the same value, but a different representation of it.

>>> x # result returned by C#
-4025962189194561064516553363283375014525921961557175720338529077112971710311848366234203913802556580292548393361209331638020083844074732374616343653135077799402946400533385408838985464487221381056062706959966844828188406680815976045839849337092509291814967568127589935214307295687077940893465121894442245470126915769901660325457529592729859443914551917517655171549159468233372814554103351084536838316208603471169266662039167296594675085295938849603548128017384775032304908588861826301095512209694112961080272106412321025934327013828425487280677537982063915874200399589997896633613461631025068511458444974149152947749747984549594822000420708352393424384641432718686749229405669436317664008070112083271636922781745940251494349374415266883563753139424535520085753958356376469108498554786941521255255003415937460671624180845917463097501347690828778209895285876290213489273200505952380626734459377765095025966725691306820725825499
>>> y # result returned by Python
1783643806175396998275362602355826387650690265345724813364371805666764467579142495237890860674783000854825016824437046690023645956675737723594580834731857259761425187634662132104996180029411374011438919474589553364998222309255272614979511868027284402170465728908528297700102876189729595563926155962569604427283291749203673030343591516627038015511719927953742781126799972560120257074290771695973286302279629131295383214811291564651109155633319576684151577295199734593114604874743329126921653504771250132941337184148762999959335547394147714802188259839801355116944682610659081543579365393513921728510730572041617697936145453462119608425988630323921319186513104423344823774870759265115372373731593225388193828408607005773987710556891304121163609340263880054616842988101393815039937434342691332663137114581535172021453932283969024301846449291944006405969946744999443455011016318658938083030075774742259090377978078691693422518308
>>> y - x # your modulus
5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807
Frank Yellin
  • 9,127
  • 1
  • 12
  • 22
  • I don't quite understand what you are talking about. We are not talking about signed/unsigned bytes in both languages. The results are 10-digit numbers. – Joshua Son Dec 03 '22 at 06:55
  • Forget about exponentiation. Calculate "-2 mod 5" in both Python and C#. One will give you 3, and the other will give you -2. That effect, but with much larger numbers, is all that you're seeing. Python's "modulus" operation is the mathematical operation "modulus" while C# is closer to "remainder". – Frank Yellin Dec 03 '22 at 07:12
  • And you're not dealing with 10-digit numbers, you're dealing with 1000-digit numbers. – Frank Yellin Dec 03 '22 at 07:14
  • Does this mean that I have to add up modulus right after C# ModPow? – Joshua Son Dec 03 '22 at 07:30
  • If the answer is negative, then add the modulus. Alternatively and simpler, if "a" is negative, add the modulus to "a" so that it is positive, and you won't end up with a negative answer. – Frank Yellin Dec 03 '22 at 20:10
  • Due to some more research, I'd like to take your answer and many thanks to you. – Joshua Son Jan 02 '23 at 16:33