Fermat's little theorem in JS - javascript

I just tried to implement Fermat's little theorem in JavaScript. I tried it both ways, a^(p-1) mod p = 1 and a^p mod p = a mod p.
function fermat(a, p) {
return (((a ^ (p - 1)) % p) === 1);
}
and
function fermat(a, p) {
return ( ( a^p ) % p ) === ( a % p );
}
It doesn't work both ways, is there any way to fix that?

In Javascript ^ means XOR. For exponentiation you need Math.pow(x, y).
function fermat(a, p) {
return Math.pow(a, p - 1) % p === 1;
}

Instead of ^, you need to use Math.pow

In addition to the ^ vs. Math.pow() issue others have pointed out, the next hurdle
you will likely face is the limited precision of the Javascript built-in numeric
types. You will very quickly exceed the range of exactly representable Javascript
numbers once the exponents start getting large, as they will be if you're wanting
to use a routine like this as a primality test. You may want to look into
a Javascript bignum library (for example, this one) that supports exponentiation
and modulus for arbitrarily large integers.

In javascript, the carat (^) is the XOR operator. What you want to use is the Math.pow(x,y) function which is equivalent to x^y.

Here is my code (JavaScript) for checking whether a number is prime based on Fermat Little Theorem.
function getRandomInt(min,max) { /* getting a random between given max and min values */
min = Math.ceil(min);
max = Math.ceil(max);
return Math.floor(Math.random()*(max-min))+min;
}
function getGCD(a,b) { /* getting the greatest common divisor */
var tmp;
while (b !== 0) {
tmp = b;
b = a%b;
a = tmp;
}
return a;
}
function getPower(a,b,p) { /* getting the a^b mod p */
if (b == 1)
return a%p;
else {
x = getPower(a,Math.floor(b/2),p);
if (b%2 == 0)
return (x*x)%p;
else return (((x*x)%p)*a)%p;
}
}
function fermatTesting(Num) { //Checking Num by using Fermat's theorem
var a = getRandomInt(2,Num-1);
if (getGCD(a,Num) !== 1) {
return "COMPOSITE";
}
else {
if (getPower(a,Num-1,Num) !== 1) {
return "COMPOSITE";
}
else {
return "PRIME";
}
}
}
console.log(fermatTesting(57)); //Displays "COMPOSITE"

There's nothing like answering an eleven year old question!
Since it's now 2021 we have support for BigInt, which supports arbitrary precision along with the exponentiation operator (**) and the modulus operator(%).
The function in the accepted answer can be rewritten as
function fermat(a, p) {
return (a**(p-1n) % p) === 1n;
}
where a and p are BigInt values.

Related

Check Odd numbers without modulo operator

I am creating a function that returns whether the passed in number is odd Without the modulo operator. The tricky part is that it should work for NEGATIVE numbers and ZERO.
here's my codes so far:
function testodd(num) {
return (num/2)*2==num;
}
var output = testodd(17);
console.log(output); // --> true
Am I making some mistakes here? Or is there a better way to do this?
you can use Bitwise operator and get same result. does this help.
<script type="text/javascript">
function oddOrEven(x) {
return ( x & 1 ) ? "odd" : "even";
}
console.log(oddOrEven(10));
</script>
For more detail about bitwise operator
Hi you can do it with bitwise AND (&) operator to check if a number is even or odd.
function testodd(num) {
if((num & 1) == 0){
return true
}
return false;
}
var output = testodd(17);
console.log(output); // --> false
var output = testodd(-16);
console.log(output); // --> true
var output = testodd(0);
console.log(output); // --> true
Try a bit-wise operation
function testodd(num) {
return num & 1; // num AND 0x1 checks for the least significant bit, indicating true or falsey
}
Remove the decimal part after division using Math.floor.
Math.floor(num / 2) * 2 === num;
For even numbers, there is no loss in decimal value. For odd numbers, decimal point value will be lost and comparison will falsy.
Here is a horribly inefficient method using recursion:
function checkOdd(num)
{
num = Math.abs(num);
if(num==0)
return false;
else if(num==1)
return true;
else
return checkOdd(num-2);
}
Of course you should never use it.
Since there's already an answer I will show you an alternative away of doing it with regex
function checkOdd(num){
console.log(/^\d*[13579]$/.test(num));
}
checkOdd(105);
Would only work with reasonably sized integers
Try
function testodd(num){
if num < 0{
var number = -num
}
int i = 1;
int product = 0;
while (product <= num)
{
product = divisor * i;
i++;
}
// return remainder
return num - (product - divisor);
}
Use this function to check if a number is odd or even, without using the modulo operator %. This should work for negative numbers and zero.
function checkOdd(num) {
// your code here
if(num<0){ //Check if number is negative
num=-num; //Convert it into positive number
}
let b=Math.floor(num/2) //Taking value for loop iteration
for(var i=1;i<=b;i++){
num=num-2; //Will check the number is odd if it subtraction end to 1 by decrementing -2 to the number
if(num==1){
return true; //return true if number is odd
}
}
return false; //return false if number is even
}
You can use isInteger method
function isEven(n){
return Number.isInteger(n / 2);
}
function odd(num) {
if (num === 0) {
return false;
}
num = Math.abs(num);
while (num >= 2) {
num = num - 2;
}
if (num === 1) {
return true;
} else {
return false;
}
}
Even number
lets take an even number say 6;
6 divided by 2 is 3;
Math.round(3) is 3;
Math.floor(3) is 3;
3===3 eveluates to true so 6 is an even number;
Odd number
lets take an odd number say 9;
9 divided by 2 is 4.5;
Math.round(4.5) is 5;
Math.floor(4.5) is 4;
5===4 evaluates to false so 9 is an odd number;
function evenChecked(num) {
if (Math.round(num / 2) === Math.floor(num / 2)) {
return `${num} is even`;
} else {
return `${num} is odd`;
}
}
console.log(evenChecked(23));
console.log(evenChecked(90));
console.log(evenChecked(56));
console.log(evenChecked(49));

Reduce a multi-digit to one-digit -guidance not answer please

goal: take a number like 54321, add the numbers together (5+4+3+2+1 = 15), then take that number (15) add the digits (1+5 = 6), so return 6;
here is my code:
function digital_root(n) {
if (n >=10) {
var digits = n.toString().split('').map(function(item, index) {return parseInt(item)}).reduce(function(a,b){ return a+b});
console.log(digits);
}
}
digital_root(1632)
Can't figure out: How to get that function to repeat over and over until digits is just one number (i.e. less than 10). I have tried a variety of nested functions, but can't seem to get it right.
If possible please point me in the direction to the solution ("try a nesting in a while... or read up on..."), but don't give me the complete code solution ("Use this code chunk:...."). I've developed a bad habit of just reading and copying...
Thank you!
Try this: reference HERE
function digital_root(n) {
var singlesum = 0;
while (n >= 10 ) {
singlesum=0;
while (n > 0) {
var rem;
rem = n % 10;
singlesum = singlesum + rem;
n = parseInt(n / 10);
}
n = singlesum;
}
console.log(singlesum);
}
digital_root(1632)
You can use recursion to solve this.
Write a function makeSingleDigit, which argument will be your number.
You need a base condition with the base step, which in your case stops the recursion when received number is one-digit and returns the number.
If condition is not true, you just need to get another digit from the number by n%10 and sum it with the makeSingleDigit(Math.floor(n/10)). By this, you repeatedly sum digits of new numbers, until function receives one-digit number.
Mathematical solution just for your information: the number, which you want to find is n % 9 === 0 ? 9 : n % 9, thus it is the remainder of the division by 9 if it is not 0, otherwise it is 9.
Here is a very optimal solution to the problem:
function digital_root(n) {
return (n - 1) % 9 + 1;
}
const result = digital_root(1632);
console.log(result);
Well, not a very good solution but you can give a hit.
function digital_root(n) {
if (n >=10) {
var digits = n.toString().split('').map(function(item, index) {return parseInt(item)}).reduce(function(a,b){ return a+b});
console.log(digits);
return(digits);
}
}
var num = 1632;
do{
num = digital_root(num);
}while(num>10);

Index of a really big Fibonacci Number

I need to calculate the index of a Fibonacci number with JavaScript, within the Fibonacci sequence. I need to do this without using recursion, or a loop. I found the following formula in the Math forum:
n=⌊logφ(F⋅5√+12)⌋
and coded it in JavaScript:
function fibIndex(fib)
{
fib = BigNumber(fib);
return logBasePhi(fib.times(Math.sqrt(5)).plus((1/2)));
}
function phi()
{
return (1 + Math.sqrt(5))/ 2;
}
function getBaseLog(x, y) {
return Math.log(y) / Math.log(x);
}
function logBasePhi(x)
{
return getBaseLog(phi(), x);
}
Notice the .times() and .plus() functions that are part of this BigNumber Library that has been extremely useful up to this point. This works fine, until the Fibonacci number I want to find the index for is really big.
The problem:
I need a different way to calculate the logarithm with such a big number. If I have a really big number, such as Fibonacci of 2000, I get Infinity for obvious reasons. The library itself does not have any methods to calculate the log, and I can't write this function either.
I would have never imagined that the logarithm of any number with such a small base (phi) can be bigger than the max for JavaScript integers. Can you guys point me in the right direction? Should I just leave it at obtaining the index for numbers less than Fib(1500) and call it good?
You can use BigInteger. You can see an example of how to use it here: http://reallifejs.com/the-meat/calculators/big-number-calculator/
For anyone else looking for this function, here it is using this BigInteger library:
function fibIndex(fib)
{
fib = BigInteger(fib);
var x = fib.multiply(Math.sqrt(5)).add((1/2));
return Math.round(x.log() / Math.log(phi()));
}
function phi()
{
return (1 + Math.sqrt(5))/ 2;
}
I still use the same equation explained in my question above, and it returns the index of Fibonacci's of any size.
fibIndex("35522938794321715091272953991088875073660950670711879743399900326436254083421380378927750257524675311447286915610820861302904371152466182968261111009824391725637150862745505342130220586979511719255023895335108709522075314248260664483166479670588221585277069887873168196490963561219694518077864879100421788205515385380434545975662001723555342440392621808579760295648531141638822913590607533540054087452041707826153271185259107394199852367649618298517093117009455894918353503525076230125819543123779319167440820789626564459764725339684808290073756385496248142195843240135064507885354877296572024804408624272941753639812538039913142028651903030529871116793317789757893606550341466951324756526825899737667945813833853722262630433262780974915425005732866591818868174705546087022106127052877310847951571707582794820376128579789767721485109492542287764348615868723395725124814856415577763540656765591673162724146048330852788081439178288706881889502843933839383437965572895385440792960391702268984769357859686271266574632871727046024303184663919395401465801528726015901456333025573481247959101652204602988035141532490361245742139050819433077833707742246312835208439293469725777437940254819086871672146128972238328251414589544434435170261367824782155103657578194196270111748570034449297964612564456266891635499257186520205662004190179581465184858273590634696557067719668344569716772604494379268256417559005989196664062339943367426392267549671696091620704483335705235401024668972377058959013548701899237423163317609813480075906438821567501678027453981255872940165896765562906948275888682233026018398591561683968279253311810352982216449990605138841279476258998291555393112171672512247299540528273985304628059093340049555047981741901553118436996372565143437092164040501385121979087826864836002852441013290435451405818936965791830088594057993174801701555239838033825491101182302604693483923297155552732646664230339899386949247469662146601783799159535265663192798622519600080199294778264021930327804674406845390858689361183645138036024622999759181149374409868339056190354930762438018253181839721998646473911299168577029520666199783681191268719288387969624745653240780708319950931159323616116725759084631179863296728766212415593748082930558151101350076376704295363472805637813559350925898715117938481138744212886965977892516525139040863376874438253015614485120277306681922196720541898193702570355885540352668267759850827312025869672621201575016416207760471674541668295376322809412095582968275396449970226064500618788480102243996614437085271546164050332641040829307354667753670012241015315160013952802535500838629086649248253271677865717482331893600871123634025348607623548331397239596180750809096946397974233223417735790158178612741331748855629088340732705900553246041710742016160018303725512211509204034880759596775427996675371964469431717567054234107252511625358715489171574578479304777517899774723598872665991091538945488811618222438651723224465992160327444696552759313881273021480919406887970238509074105071808066821703115066838126027585207922256205186141921352880657758551963602504587265334948468963725795943612659061581738118921217900480358979991209140061985794462152498458564473369295078153567296201818251720281822962062936831573631653751528074225190111823253702351177610664803940345503699699208037095784870495785646943997234474258262569998608041243140247674073513323374199936066218946098722092264140092669753657824017634461763981521997119226219136508584203375683292957948563073632975937642581947768042371117470198355444599517718979158713784804470849343173517943800269775988799065209263727016757620989100649249277790139290067789688270481157537247255077854388424596882337360026236416764073030845206282134294301701605369452555608749844089881840152464688185413471165531348083450071936767808847178828505212544681448346850412422392584457798023562617507156540143036586660455094150665003248778589943633804236061867787254092465761897721097498706848304838082130151573830146281598905862080528755999259386441406295844212093958532689277331339576745477613093048842162872506248493879631984787279577095875465635013803960469019743694441996546910736934590725390122252181310568062868015617422771375425422209106466232597689466636780861666245204430735375550444974466951762888881642801337840709202391876433786768647147807880162471534334272202034098411011768290957484345424507121327462388443014612800575348423810123382495642833743034606424879522789397956839996920113680951463518836156462019057063161795046895734075593501902084338246542048532779483281408634769806186279989881229648075555962086774926497206070780542404761166097604241890965888018873735027199940548827053350115337885438800728312460914286268127990478092896975620706029422142841447344514680046143167682001640750053397540223424322177217456434741847020047763710403144096996427837529811812126999093061373016438435440619803496909856986800826405322182728111872725881192065183612822832173197471616932926246556344247662468294551754101114527143077792003917544284111176961413199426663155326179333146951914261328112918116870606040456416800180399145364936151721824514256765308265696290759951243242140057433018143404698921069198350343599629915865217541917472815612277351716569260985624821969133328022587501");
will return 25,001, which is the index of the above fib.
Instead use this formula:
(Fn) = (Fn-1) + (Fn-2)
n is a subindex, for understanding I say...
So let's code :D
function fibonacci(n) {
var f = new Array();
f[0] = 1;
f[1] = 1;
if(n == 1 && n == 2) {
return 1;
}
for(var i = 2; i < n; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f[n - 1];
}

Recursion "maximum call stack size exceeded" - decimal to hexadecimal converter

I'm trying to make a decimal to hexadecimal converter without using Number.prototype.toString (this is an assignment which does not allow that function). I am attempting to use recursion to try to work it. Everything works until the else inside the main else if that makes any sense. It gives me that error when I run it for any number above 255 (i.e. any number which has more than 2 digits in hexadecimal). Does anyone know why this is the case?
var number = parseInt(prompt("Give me a number and I will turn it into hexadecimal!"));
var digit = 1;
var hexConverter = function () {
if (digit === 1) {
if (Math.floor(number / 16) === 0) {
console.log(hexDigits[number]);
} else {
digit = 16;
console.log(hexConverter(), hexDigits[number % 16]);
}
} else {
if (Math.floor(number / (digit * 16)) === 0) {
return (hexDigits[Math.floor(number / digit)]);
} else {
return (hexConverter(), hexDigits[number % (digit * 16)]);
}
digit = digit * 16;
}
};
hexConverter();
You are changing digit after making the recursive call, so it will be stuck at 16 and never get to the point where you increase it.
Move the digit = digit*16; to before the recursive call, just as you have digit = 16 in the first part.
function toHex(x) {
var res='',h;
while (x) {
res=(((h=x&15)<10)? h : String.fromCharCode(55+h)) + res;
x>>=4;
}
return res;
}
Would work quite fine.
Question to you : why only 'quite' ? :-)

Javascript toFixed function

I have a question regarding toFixed() function. If I have a float e.g. - 3.123123423 and 0. How can I output it to input box with toFixed(2) so the inputbox values would be 3.12 and 0. I mean if the value is integer I want output it without trailing .00 :)
As there is no difference between integers and floats in JavaScript, here is my quick'n'dirty approach:
theNumber.toFixed(2).replace(".00", "");
Or something generic:
myToFixed = function (n, digits) {
digits = digits || 0;
return n.toFixed(digits).replace(new RegExp("\\.0{" + digits + "}"), "");
}
myToFixed(32.1212, 2) --> "32.12"
myToFixed(32.1212, 0) --> "32"
myToFixed(32, 2) --> "32"
myToFixed(32.1, 2) --> "32.10"
You don't need Math.round():
var toFixed = function(val, n) {
var result = val.toFixed(n);
if (result == val)
return val.toString();
return result;
}
toFixed(3.123, 2) --> "3.12"
toFixed(3, 2) --> "3"
function toFixed0d(x, d)
{
if(Math.round(x) == x)
{
return x.toString();
}else
{
return x.toFixed(d);
}
}
toFixed0d(3.123123423, 2) = "3.12"
toFixed0d(0, 2) = "0"
Note that toFixed() is broken in IE and generally not to be relied on. Annoying but accurately-rounded replacement functions given there.
Number.toFixed produces some mathematically bizarre results and gives you the fractional digits you asked for, whether you need them or not.
Math.round is mathematically correct, but doesn't allow you to specify a precision.
Here's a function that's both mathematically correct (disregarding floating point errors) and that gives you what you want.
var roundToPlusInfinity = function(n, fd) {
var scale = Math.pow(10, fd),
rounded = fd ? Math.floor((n * scale + 0.5)) / scale :
Math.round(n);
return rounded.toString();
};
The algorithm is: scale up so that the digits you want are to the left of the decimal point, add .5 (so that >= .5 in the first insignificant place causes an increment of the integer portion), truncate (not round!) and scale back down. There's the potential for floating point errors to creep in, but it's a sight better than the wretched toFixed function.
Testing it out:
roundToPlusInfinity(5.53335, 4); // "5.3334"
roundToPlusInfinity(-9999.95, 1); // "-9999.9"
roundToPlusInfinity(3.00015, 3); // "3"
Because of the possibility of floating point error, the scale down might give a result like "3.00000000001", which is annoying. Something like this should take care of it.
var trimFraction = function(s, fd) {
var splitPoint = s.indexOf('.');
if (splitPoint === -1) {
return s;
}
var f = s.substring(splitPoint + 1, s.length),
i = s.substring(0, splitPoint);
if (f.length > fd) {
f = f.substring(0, fd).replace(/0+$/, "");
}
if (f) {
return i + '.' + f;
}
return i;
};
trimFraction("3.1000000001", 2); // "3.1"
You haven't made clear the rounding algorithm you want. Round towards plus infinity is the rounding you learnt at school where you round >= .5 up (i.e. towards positive infinity). I believe that in accounting, the correct rounding algorithm (outside Switzerland and Argentina at least) is away from zero. Simple:
var roundAwayFromZero = function(n, fd) {
var ret = roundToPlusInfinity(Math.abs(n), fd);
return (n < 0) ? '-' + ret : ret;
};
roundAwayFromZero(-9999.95, 1); // "-10000"
If the results are for human presentation, Intl.NumberFormat is a possibility, since you can specify both the minimum and maximum number of fractional digits. At the time of writing it's not exactly widely supported and, assuming that Chrome implements the specification correctly, uses the same impenetrable and plain wrong truncating algorithm as toFixed. Interestingly, the "currency" style uses roundAwayFromZero (or round to a half if the currency code is "CHF", which is a nice touch).
Here is a function I came up with after thinking about this same problem for a little while:
function toFixed (number, n) {
return parseFloat(number.toFixed(n));
}
As per this question, this function will return as follows:
toFixed(3.123123423, 2);
> 3.12
toFixed(0, 2);
> 0
toFixed(3.1, 2);
> 3.1
toFixed(3.005, 2);
> 3
toFixed(3.005, 3);
> 3.005
toFixed(3.0500, 4);
> 3.05
Note that the toFixed method of the JavaScript's Number object actually returns a String. The above toFixed function will return a Number. If you'd rather have a String then use the following instead:
function toFixed (number, n) {
return parseFloat(number.toFixed(n)).toString();
}

Categories