Calculated nCr mod m (n choose r) for large values of n (10^9) - modulo

Now that CodeSprint 3 is over, I've been wondering how to solve this problem. We need to simply calculate nCr mod 142857 for large values of r and n (0<=n<=10^9 ; 0<=r<=n). I used a recursive method which goes through min(r, n-r) iterations to calculate the combination. Turns out this wasn't efficient enough. I've tried a few different methods, but they all seem to not be efficient enough. Any suggestions?

For non-prime mod, factor it (142857 = 3^3 * 11 * 13 * 37) and compute C(n,k) mod p^q for each prime factor of the mod using the general Lucas theorem, and combine them using Chinese remainder theorem.
For example, C(234, 44) mod 142857 = 6084, then
C(234, 44) mod 3^3 = 9
C(234, 44) mod 11 = 1
C(234, 44) mod 13 = 0
C(234, 44) mod 37 = 16
The Chinese Remainder theorem involves finding x such that
x = 9 mod 3^3
x = 1 mod 11
x = 0 mod 13
x = 16 mod 37
The result is x = 6084.
Example
C(234, 44) mod 3^3
First convert n, k, and n-k to base p
n = 234_10 = 22200_3
k = 44_10 = 1122_3
r = n-k = 190_10 = 21001_3
Next find the number of carries
e[i] = number of carries from i to end
e 4 3 2 1 0
1 1
r 2 1 0 0 1
k 1 1 2 2
n 2 2 2 0 0
Now create the factorial function needed for general Lucas
def f(n, p):
r = 1
for i in range(1, n+1):
if i % p != 0:
r *= i
return r
Since q = 3, you will consider only three digits of the base p representation at a time
So
f(222_3, 3)/[f(210_3, 3) * f(011_3, 3)] *
f(220_3, 3)/[f(100_3, 3) * f(112_3, 3)] *
f(200_3, 3)/[f(001_3, 3) * f(122_3, 3)] = 6719344775 / 7
Now
s = 1 if p = 2 and q >= 3 else -1
Then
p^e[0] * s * 6719344775 / 7 mod 3^3
e[0] = 2
p^e[0] = 3^2 = 9
s = -1
p^e[0] * s * 6719344775 = -60474102975
Now you have
-60474102975 / 7 mod 3^3
This is a linear congruence and can be solved with
ModularInverse(7, 3^3) = 4
4 * -60474102975 mod 27 = 9
Hence C(234, 44) mod 3^3 = 9

Related

How to find and update levels accordingly based on points?

I am creating a rails application which is like a game. So it has points and levels. For example: to become level one the user has to get atleast 100 points and again for level two the user has to reach level 2 the user has to collect 200 points. The level difference changes after every 10 levels i.e., The difference between each level changes after 10 levels always. By that I mean the difference in points between level one and two is 100 and the difference in points in level 11 and 12 is 150 and so on. There is no upper bound for levels.
Now my question is let's say a user's total points is 3150 and just got updated to 3155. What's the optimal solution to find the current level and update it if needed?
I can get a solution using while loops and again looping inside it which will give a result in O(n^2). I need something better.
I think this code works but I'm not sure if this is the best way to go about it
def get_level(points)
diff = 100
sum = 0
level = -1
current_level = 0
while level.negative?
10.times do |i|
current_level += 1
sum += diff
if points > sum
next
elsif points <= sum
level = current_level
break
end
end
diff += 50
end
puts level
end
I wrote a get_points function (it should not be difficult). Then based on it get_level function in which it was necessary to solve the quadratic equation to find high value, and then calc low.
If you have any questions, let me know.
Check output here.
#!/usr/bin/env python3
import math
def get_points(level):
high = (level + 1) // 10
low = (level + 1) % 10
high_point = 250 * high * high + 750 * high # (3 + high) * high // 2 * 500
low_point = (100 + 50 * high) * low
return low_point + high_point
def get_level(points):
# quadratic equation
a = 250
b = 750
c = -points
d = b * b - 4 * a * c
x = (-b + math.sqrt(d)) / (2 * a)
high = int(x)
remainder = points - (250 * high * high + 750 * high)
low = remainder // (100 + 50 * high)
level = high * 10 + low
return level
def main():
for l in range(0, 40):
print(f'{l:3d} {get_points(l - 1):5d}..{get_points(l) - 1}')
for level, (l, r) in (
(1, (100, 199)),
(2, (200, 299)),
(9, (900, 999)),
(10, (1000, 1149)),
(11, (1150, 1299)),
(19, (2350, 2499)),
(20, (2500, 2699)),
):
for p in range(l, r + 1): # for in [l, r]
assert get_level(p) == level, f'{p} {l}'
if __name__ == '__main__':
main()
Why did you set the value of a=250 and b = 750? Can you explain that to me please?
Let's write out every 10 level and the difference between points:
lvl - pnt (+delta)
10 - 1000 (+1000 = +100 * 10)
20 - 2500 (+1500 = +150 * 10)
30 - 4500 (+2000 = +200 * 10)
40 - 7000 (+2500 = +250 * 10)
Divide by 500 (10 levels * 50 difference changes) and received an arithmetic progression starting at 2:
10 - 2 (+2)
20 - 5 (+3)
30 - 9 (+4)
40 - 14 (+5)
Use arithmetic progression get points formula for level = k * 10 equal to:
sum(x for x in 2..k+1) * 500 =
(2 + k + 1) * k / 2 * 500 =
(3 + k) * k * 250 =
250 * k * k + 750 * k
Now we have points and want to find the maximum high such that point >= 250 * high^2 + 750 * high, i. e. 250 * high^2 + 750 * high - points <= 0. Value a = 250 is positive and branches of the parabola are directed up. Now we find the solution of quadratic equation 250 * high^2 + 750 * high - points = 0 and discard the real part (is high = int(x) in python script).

How to do money breakdown in Cobol

My code:
A-0000.
DISPLAY "Enter Number :".
ACCEPT NUM.
IF NUM >=1000 THEN
COMPUTE WS-B = NUM / 1000
COMPUTE NUM = NUM - (WS-B * 500)
IF NUM >=500 THEN
COMPUTE WS-B = NUM / 500
COMPUTE NUM = NUM - (WS-B * 500)
IF NUM >=200 THEN
COMPUTE WS-C = NUM / 200
COMPUTE NUM=NUM- (WS-C * 200)
IF NUM >=100 THEN
COMPUTE WS-D = NUM / 100
COMPUTE NUM = NUM - (WS-D * 100)
IF NUM >=50 THEN
COMPUTE WS-E = NUM / 50
COMPUTE NUM = NUM - (WS-E * 50)
IF NUM >=20 THEN
COMPUTE WS-F = NUM / 20
COMPUTE NUM = NUM- (WS-F * 20)
IF NUM >=10 THEN
COMPUTE WS-G = NUM / 10
COMPUTE NUM = NUM - (WS-G * 10)
IF NUM >=5 THEN
COMPUTE WS-H = NUM / 5
COMPUTE NUM = NUM - (WS-H * 5)
IF NUM >=1 THEN
MOVE NUM TO WS-I
END-IF.
Problem statement:
Create a program that enters a number and determine how many of the following monetary value will be given.
1, 000
500
200
100
50
20
10
5
1
You probably meant to use WS-A here instead of using WS-B twice, once for 1000's and again for 500.
IF NUM >=1000 THEN
COMPUTE WS-A = NUM / 1000
COMPUTE NUM = NUM - (WS- * 500)
END-IF
Use the END-IF scope terminator after all IF statements or you run the risk of nesting them which is not what you want to do for a sieve.

SHA512 pure Lua 5.1 adaptation

I was searching for a pure Lua 5.1 adaptation for SHA512 and yielded no results anywhere I went. I found a similar question where someone tried to convert the SHA256 adaptation into SHA512 (except he was using Lua 5.3):
Adaptation of SHA2 512 gives incorrect results
Basically I couldn't use bitwise operators (not implemented in Lua 5.1) so I had to write my own implementations of them.
This is my code:
local MOD = 2^64;
local MODM = MOD-1;
local function memoize(f)
local mt = {}
local t = setmetatable({}, mt)
function mt:__index(k)
local v = f(k)
t[k] = v
return v
end
return t
end
local function make_bitop_uncached(t, m)
local function bitop(a, b)
local res,p = 0,1
while a ~= 0 and b ~= 0 do
local am, bm = a % m, b % m
res = res + t[am][bm] * p
a = (a - am) / m
b = (b - bm) / m
p = p*m
end
res = res + (a + b) * p
return res
end
return bitop
end
local function make_bitop(t)
local op1 = make_bitop_uncached(t,2^1)
local op2 = memoize(function(a) return memoize(function(b) return op1(a, b)
end) end)
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
end
local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
local function bxor(a, b, c, ...)
local z = nil
if b then
a = a % MOD
b = b % MOD
z = bxor1(a, b)
if c then z = bxor(z, c, ...) end
return z
elseif a then return a % MOD
else return 0 end
end
local function band(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = ((a + b) - bxor1(a,b)) / 2
if c then z = bit32_band(z, c, ...) end
return z
elseif a then return a % MOD
else return MODM end
end
local function bnot(x) return (-1 - x) % MOD end
local function rshift1(a, disp)
if disp < 0 then return lshift(a,-disp) end
return math.floor(a % 2 ^ 32 / 2 ^ disp)
end
local function rshift(x, disp)
if disp > 31 or disp < -31 then return 0 end
return rshift1(x % MOD, disp)
end
local function lshift(a, disp)
if disp < 0 then return rshift(a,-disp) end
return (a * 2 ^ disp) % 2 ^ 32
end
-- UTILITY FUNCTIONS
--
-- transform a string of bytes in a string of hexadecimal digits
local function str2hexa (s)
local h = string.gsub(s, ".", function(c)
return string.format("%02x", string.byte(c))
end)
return h
end
-- transforms number 'l' into a big-endian sequence of 'n' bytes
--(coded as a string)
local function num2string(l, n)
local s = ""
for i = 1, n do
--most significant byte of l
local remainder = l % 256
s = string.char(remainder) .. s
--remove from l the bits we have already transformed
l = (l-remainder) / 256;
end
return s
end
-- transform the big-endian sequence of eight bytes starting at
-- index 'i' in 's' into a number
local function s264num (s, i)
local n = 0
for i = i, i + 7 do
n = n*256 + string.byte(s, i)
end
return n
end
--
-- MAIN SECTION
--
-- FIRST STEP: INITIALIZE HASH VALUES
--(second 32 bits of the fractional parts of the square roots of the first
9th through 16th primes 23..53)
local HH = {}
local function initH512(H)
H = {0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}
return H
end
-- SECOND STEP: INITIALIZE ROUND CONSTANTS
--(first 80 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
local k = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
}
-- THIRD STEP: PRE-PROCESSING (padding)
local function preprocess(toProcess, len)
--append a single '1' bit
--append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K = 896mod1024
local extra = - (len + 17) % 128 + 8
len = num2string(8 * len, 8)
toProcess = toProcess .. "\128" .. string.rep("\0", extra) .. len
assert(#toProcess % 128 == 0)
return toProcess
end
local function rrotate(rot, n)
return rshift(rot, n) or (rshift(rot, 64 - n))
end
local function digestblock(msg, i, H)
local w = {}
for j = 1, 16 do w[j] = s264num(msg, i + (j - 1) * 8) end
for j = 17, 80 do
local v = w[j - 15]
local s0 = bxor(rrotate(v, 1), rrotate(v, 8), rshift(v, 7))
v = w[j - 2]
w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 19), rrotate(v, 61),
rshift(v, 6))
end
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
for i = 1, 80 do
a, b, c, d, e, f, g, h = a , b , c , d , e , f , g , h
local s0 = bxor(rrotate(a, 28), rrotate(a, 34), rrotate(a, 39))
local maj = bxor(band(a, b), band(a, c), band(b, c))
local t2 = s0 + maj
local s1 = bxor(rrotate(e, 14), rrotate(e, 18), rrotate(e, 41))
local ch = bxor (band(e, f), band(bnot(e), g))
local t1 = h + s1 + ch + k[i] + w[i]
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
end
H[1] = (H[1] + a)
H[2] = (H[2] + b)
H[3] = (H[3] + c)
H[4] = (H[4] + d)
H[5] = (H[5] + e)
H[6] = (H[6] + f)
H[7] = (H[7] + g)
H[8] = (H[8] + h)
end
local function finalresult512 (H)
-- Produce the final hash value:
return
str2hexa(num2string(H[1], 8)..num2string(H[2], 8)..num2string(H[3], 8)..num2string(H[4], 8)..
num2string(H[5], 8)..num2string(H[6], 8)..num2string(H[7], 8)..num2string(H[8], 8))
end
-- Returns the hash512 for the given string.
local function hash512 (msg)
msg = preprocess(msg, #msg)
local H = initH512(HH)
-- Process the message in successive 1024-bit (128 bytes) chunks:
for i = 1, #msg, 128 do
digestblock(msg, i, H)
end
return finalresult512(H)
end
print( hash512("a") )
At the end, when "a" is hashed, it turns into this:
8c14f3e36400000074d6c495c0000000fd2e4ad8b40000009a78880fb00000002c13f4fdc0000000bf50f67658000000cdf76c796c000000df8163cae8000000
Instead of the actual hash (which is this):
1F40FC92DA241694750979EE6CF582F2D5D7D28E18335DE05ABC54D0560E0F5302860C652BF08D560252AA5E74210546F369FBBBCE8C12CFC7957B2652FE9A75
So my question is, why is it wielding such different results. Is it a problem with the bitwise operator functions? I am stumped.
Here is a working implementation of SHA512 for Lua 5.1
File sha2for51.lua
-- This module contains functions to calculate SHA2 digest.
-- Supported hashes: SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
-- This is a pure-Lua module, compatible with Lua 5.1
-- It works on Lua 5.1/5.2/5.3/5.4/LuaJIT, but it doesn't use benefits of Lua versions 5.2+
-- Input data may must be provided either as a whole string or as a sequence of substrings (chunk-by-chunk).
-- Result (SHA2 digest) is a string of lowercase hex digits.
--
-- Simplest usage example:
-- local your_hash = require("sha2for51").sha512("your string")
-- See file "sha2for51_test.lua" for more examples.
local unpack, table_concat, byte, char, string_rep, sub, string_format, floor, ceil, min, max =
table.unpack or unpack, table.concat, string.byte, string.char, string.rep, string.sub, string.format, math.floor, math.ceil, math.min, math.max
--------------------------------------------------------------------------------
-- BASIC BITWISE FUNCTIONS
--------------------------------------------------------------------------------
-- 32-bit bitwise functions
local AND, OR, XOR, SHL, SHR, ROL, ROR, HEX
-- Only low 32 bits of function arguments matter, high bits are ignored
-- The result of all functions (except HEX) is an integer (pair of integers) inside range 0..(2^32-1)
function SHL(x, n)
return (x * 2^n) % 4294967296
end
function SHR(x, n)
x = x % 4294967296 / 2^n
return x - x % 1
end
function ROL(x, n)
x = x % 4294967296 * 2^n
local r = x % 4294967296
return r + (x - r) / 4294967296
end
function ROR(x, n)
x = x % 4294967296 / 2^n
local r = x % 1
return r * 4294967296 + (x - r)
end
local AND_of_two_bytes = {} -- look-up table (256*256 entries)
for idx = 0, 65535 do
local x = idx % 256
local y = (idx - x) / 256
local res = 0
local w = 1
while x * y ~= 0 do
local rx = x % 2
local ry = y % 2
res = res + rx * ry * w
x = (x - rx) / 2
y = (y - ry) / 2
w = w * 2
end
AND_of_two_bytes[idx] = res
end
local function and_or_xor(x, y, operation)
-- operation: nil = AND, 1 = OR, 2 = XOR
local x0 = x % 4294967296
local y0 = y % 4294967296
local rx = x0 % 256
local ry = y0 % 256
local res = AND_of_two_bytes[rx + ry * 256]
x = x0 - rx
y = (y0 - ry) / 256
rx = x % 65536
ry = y % 256
res = res + AND_of_two_bytes[rx + ry] * 256
x = (x - rx) / 256
y = (y - ry) / 256
rx = x % 65536 + y % 256
res = res + AND_of_two_bytes[rx] * 65536
res = res + AND_of_two_bytes[(x + y - rx) / 256] * 16777216
if operation then
res = x0 + y0 - operation * res
end
return res
end
function AND(x, y)
return and_or_xor(x, y)
end
function OR(x, y)
return and_or_xor(x, y, 1)
end
function XOR(x, y, z) -- 2 or 3 arguments
if z then
y = and_or_xor(y, z, 2)
end
return and_or_xor(x, y, 2)
end
function HEX(x)
return string_format("%08x", x % 4294967296)
end
-- Arrays of SHA2 "magic numbers"
local sha2_K_lo, sha2_K_hi, sha2_H_lo, sha2_H_hi = {}, {}, {}, {}
local sha2_H_ext256 = {[224] = {}, [256] = sha2_H_hi}
local sha2_H_ext512_lo, sha2_H_ext512_hi = {[384] = {}, [512] = sha2_H_lo}, {[384] = {}, [512] = sha2_H_hi}
local common_W = {} -- a temporary table shared between all calculations
local function sha256_feed_64(H, K, str, W, offs, size)
-- offs >= 0, size >= 0, size is multiple of 64
for pos = offs, size + offs - 1, 64 do
for j = 1, 16 do
pos = pos + 4
local a, b, c, d = byte(str, pos - 3, pos)
W[j] = ((a * 256 + b) * 256 + c) * 256 + d
end
for j = 17, 64 do
local a, b = W[j-15], W[j-2]
W[j] = XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) + W[j-7] + W[j-16]
end
local a, b, c, d, e, f, g, h, z = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
for j = 1, 64 do
z = XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + AND(e, f) + AND(-1-e, g) + h + K[j] + W[j]
h = g
g = f
f = e
e = z + d
d = c
c = b
b = a
a = z + AND(d, c) + AND(a, XOR(d, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10))
end
H[1], H[2], H[3], H[4] = (a + H[1]) % 4294967296, (b + H[2]) % 4294967296, (c + H[3]) % 4294967296, (d + H[4]) % 4294967296
H[5], H[6], H[7], H[8] = (e + H[5]) % 4294967296, (f + H[6]) % 4294967296, (g + H[7]) % 4294967296, (h + H[8]) % 4294967296
end
end
local function sha512_feed_128(H_lo, H_hi, K_lo, K_hi, str, W, offs, size)
-- offs >= 0, size >= 0, size is multiple of 128
-- W1_hi, W1_lo, W2_hi, W2_lo, ... Wk_hi = W[2*k-1], Wk_lo = W[2*k]
for pos = offs, size + offs - 1, 128 do
for j = 1, 32 do
pos = pos + 4
local a, b, c, d = byte(str, pos - 3, pos)
W[j] = ((a * 256 + b) * 256 + c) * 256 + d
end
local tmp1, tmp2
for jj = 17 * 2, 80 * 2, 2 do
local a_lo, a_hi, b_lo, b_hi = W[jj-30], W[jj-31], W[jj-4], W[jj-5]
tmp1 = XOR(SHR(a_lo, 1) + SHL(a_hi, 31), SHR(a_lo, 8) + SHL(a_hi, 24), SHR(a_lo, 7) + SHL(a_hi, 25)) + XOR(SHR(b_lo, 19) + SHL(b_hi, 13), SHL(b_lo, 3) + SHR(b_hi, 29), SHR(b_lo, 6) + SHL(b_hi, 26)) + W[jj-14] + W[jj-32]
tmp2 = tmp1 % 4294967296
W[jj-1] = XOR(SHR(a_hi, 1) + SHL(a_lo, 31), SHR(a_hi, 8) + SHL(a_lo, 24), SHR(a_hi, 7)) + XOR(SHR(b_hi, 19) + SHL(b_lo, 13), SHL(b_hi, 3) + SHR(b_lo, 29), SHR(b_hi, 6)) + W[jj-15] + W[jj-33] + (tmp1 - tmp2) / 4294967296
W[jj] = tmp2
end
local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo, z_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi, z_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
for j = 1, 80 do
local jj = 2 * j
tmp1 = XOR(SHR(e_lo, 14) + SHL(e_hi, 18), SHR(e_lo, 18) + SHL(e_hi, 14), SHL(e_lo, 23) + SHR(e_hi, 9)) + AND(e_lo, f_lo) + AND(-1-e_lo, g_lo) + h_lo + K_lo[j] + W[jj]
z_lo = tmp1 % 4294967296
z_hi = XOR(SHR(e_hi, 14) + SHL(e_lo, 18), SHR(e_hi, 18) + SHL(e_lo, 14), SHL(e_hi, 23) + SHR(e_lo, 9)) + AND(e_hi, f_hi) + AND(-1-e_hi, g_hi) + h_hi + K_hi[j] + W[jj-1] + (tmp1 - z_lo) / 4294967296
h_lo = g_lo
h_hi = g_hi
g_lo = f_lo
g_hi = f_hi
f_lo = e_lo
f_hi = e_hi
tmp1 = z_lo + d_lo
e_lo = tmp1 % 4294967296
e_hi = z_hi + d_hi + (tmp1 - e_lo) / 4294967296
d_lo = c_lo
d_hi = c_hi
c_lo = b_lo
c_hi = b_hi
b_lo = a_lo
b_hi = a_hi
tmp1 = z_lo + AND(d_lo, c_lo) + AND(b_lo, XOR(d_lo, c_lo)) + XOR(SHR(b_lo, 28) + SHL(b_hi, 4), SHL(b_lo, 30) + SHR(b_hi, 2), SHL(b_lo, 25) + SHR(b_hi, 7))
a_lo = tmp1 % 4294967296
a_hi = z_hi + (AND(d_hi, c_hi) + AND(b_hi, XOR(d_hi, c_hi))) + XOR(SHR(b_hi, 28) + SHL(b_lo, 4), SHL(b_hi, 30) + SHR(b_lo, 2), SHL(b_hi, 25) + SHR(b_lo, 7)) + (tmp1 - a_lo) / 4294967296
end
tmp1 = H_lo[1] + a_lo
tmp2 = tmp1 % 4294967296
H_lo[1], H_hi[1] = tmp2, (H_hi[1] + a_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[2] + b_lo
tmp2 = tmp1 % 4294967296
H_lo[2], H_hi[2] = tmp2, (H_hi[2] + b_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[3] + c_lo
tmp2 = tmp1 % 4294967296
H_lo[3], H_hi[3] = tmp2, (H_hi[3] + c_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[4] + d_lo
tmp2 = tmp1 % 4294967296
H_lo[4], H_hi[4] = tmp2, (H_hi[4] + d_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[5] + e_lo
tmp2 = tmp1 % 4294967296
H_lo[5], H_hi[5] = tmp2, (H_hi[5] + e_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[6] + f_lo
tmp2 = tmp1 % 4294967296
H_lo[6], H_hi[6] = tmp2, (H_hi[6] + f_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[7] + g_lo
tmp2 = tmp1 % 4294967296
H_lo[7], H_hi[7] = tmp2, (H_hi[7] + g_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
tmp1 = H_lo[8] + h_lo
tmp2 = tmp1 % 4294967296
H_lo[8], H_hi[8] = tmp2, (H_hi[8] + h_hi + (tmp1 - tmp2) / 4294967296) % 4294967296
end
end
--------------------------------------------------------------------------------
-- CALCULATING THE MAGIC NUMBERS (roots of primes)
--------------------------------------------------------------------------------
do
local function mul(src1, src2, factor, result_length)
-- Long arithmetic multiplication: src1 * src2 * factor
-- src1, src2 - long integers (arrays of digits in base 2^24)
-- factor - short integer
local result = {}
local carry = 0
local value = 0.0
local weight = 1.0
for j = 1, result_length do
local prod = 0
for k = max(1, j + 1 - #src2), min(j, #src1) do
prod = prod + src1[k] * src2[j + 1 - k]
end
carry = carry + prod * factor
local digit = carry % 16777216
result[j] = digit
carry = floor(carry / 16777216)
value = value + digit * weight
weight = weight * 2^24
end
return
result, -- long integer
value -- and its floating point approximation
end
local idx, step, p, one = 0, {4, 1, 2, -2, 2}, 4, {1}
local sqrt_hi, sqrt_lo, idx_disp = sha2_H_hi, sha2_H_lo, 0
repeat
p = p + step[p % 6]
local d = 1
repeat
d = d + step[d % 6]
if d * d > p then
idx = idx + 1
local root = p^(1/3)
local R = mul({floor(root * 2^40)}, one, 1, 2)
local _, delta = mul(R, mul(R, R, 1, 4), -1, 4)
local hi = R[2] % 65536 * 65536 + floor(R[1] / 256)
local lo = R[1] % 256 * 16777216 + floor(delta * (2^-56 / 3) * root / p)
sha2_K_hi[idx], sha2_K_lo[idx] = hi, lo
if idx < 17 then
root = p^(1/2)
R = mul({floor(root * 2^40)}, one, 1, 2)
_, delta = mul(R, R, -1, 2)
hi = R[2] % 65536 * 65536 + floor(R[1] / 256)
lo = R[1] % 256 * 16777216 + floor(delta * 2^-17 / root)
sha2_H_ext256[224][idx + idx_disp] = lo
sqrt_hi[idx + idx_disp], sqrt_lo[idx + idx_disp] = hi, lo
if idx == 8 then
sqrt_hi, sqrt_lo, idx_disp = sha2_H_ext512_hi[384], sha2_H_ext512_lo[384], -8
end
end
break
end
until p % d == 0
until idx > 79
end
-- Calculating IV for SHA512/224 and SHA512/256
for width = 224, 256, 32 do
local H_lo, H_hi = {}, {}
for j = 1, 8 do
H_lo[j] = XOR(sha2_H_lo[j], 0xa5a5a5a5)
H_hi[j] = XOR(sha2_H_hi[j], 0xa5a5a5a5)
end
sha512_feed_128(H_lo, H_hi, sha2_K_lo, sha2_K_hi, "SHA-512/"..tonumber(width).."\128"..string_rep("\0", 115).."\88", common_W, 0, 128)
sha2_H_ext512_lo[width] = H_lo
sha2_H_ext512_hi[width] = H_hi
end
--------------------------------------------------------------------------------
-- FINAL FUNCTIONS
--------------------------------------------------------------------------------
local function sha256ext(width, text)
-- Create an instance (private objects for current calculation)
local H, length, tail = {unpack(sha2_H_ext256[width])}, 0, ""
local function partial(text_part)
if text_part then
if tail then
length = length + #text_part
local offs = 0
if tail ~= "" and #tail + #text_part >= 64 then
offs = 64 - #tail
sha256_feed_64(H, sha2_K_hi, tail..sub(text_part, 1, offs), common_W, 0, 64)
tail = ""
end
local size = #text_part - offs
local size_tail = size % 64
sha256_feed_64(H, sha2_K_hi, text_part, common_W, offs, size - size_tail)
tail = tail..sub(text_part, #text_part + 1 - size_tail)
return partial
else
error("Adding more chunks is not allowed after asking for final result", 2)
end
else
if tail then
local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64 + 1)}
tail = nil
-- Assuming user data length is shorter than 2^53 bytes
-- Anyway, it looks very unrealistic that one would spend enough time to process a 2^53 bytes of data by using this Lua script :-)
-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes
length = length * (8 / 256^7) -- convert "byte-counter" to "bit-counter" and move floating point to the left
for j = 4, 10 do
length = length % 1 * 256
final_blocks[j] = char(floor(length))
end
final_blocks = table_concat(final_blocks)
sha256_feed_64(H, sha2_K_hi, final_blocks, common_W, 0, #final_blocks)
local max_reg = width / 32
for j = 1, max_reg do
H[j] = HEX(H[j])
end
H = table_concat(H, "", 1, max_reg)
end
return H
end
end
if text then
-- Actually perform calculations and return the SHA256 digest of a message
return partial(text)()
else
-- Return function for partial chunk loading
-- User should feed every chunks of input data as single argument to this function and receive SHA256 digest by invoking this function without an argument
return partial
end
end
local function sha512ext(width, text)
-- Create an instance (private objects for current calculation)
local length, tail, H_lo, H_hi = 0, "", {unpack(sha2_H_ext512_lo[width])}, {unpack(sha2_H_ext512_hi[width])}
local function partial(text_part)
if text_part then
if tail then
length = length + #text_part
local offs = 0
if tail ~= "" and #tail + #text_part >= 128 then
offs = 128 - #tail
sha512_feed_128(H_lo, H_hi, sha2_K_lo, sha2_K_hi, tail..sub(text_part, 1, offs), common_W, 0, 128)
tail = ""
end
local size = #text_part - offs
local size_tail = size % 128
sha512_feed_128(H_lo, H_hi, sha2_K_lo, sha2_K_hi, text_part, common_W, offs, size - size_tail)
tail = tail..sub(text_part, #text_part + 1 - size_tail)
return partial
else
error("Adding more chunks is not allowed after asking for final result", 2)
end
else
if tail then
local final_blocks = {tail, "\128", string_rep("\0", (-17-length) % 128 + 9)}
tail = nil
-- Assuming user data length is shorter than 2^53 bytes
-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes
length = length * (8 / 256^7) -- convert "byte-counter" to "bit-counter" and move floating point to the left
for j = 4, 10 do
length = length % 1 * 256
final_blocks[j] = char(floor(length))
end
final_blocks = table_concat(final_blocks)
sha512_feed_128(H_lo, H_hi, sha2_K_lo, sha2_K_hi, final_blocks, common_W, 0, #final_blocks)
local max_reg = ceil(width / 64)
for j = 1, max_reg do
H_lo[j] = HEX(H_hi[j])..HEX(H_lo[j])
end
H_hi = nil
H_lo = table_concat(H_lo, "", 1, max_reg):sub(1, width / 4)
end
return H_lo
end
end
if text then
-- Actually perform calculations and return the SHA256 digest of a message
return partial(text)()
else
-- Return function for partial chunk loading
-- User should feed every chunks of input data as single argument to this function and receive SHA256 digest by invoking this function without an argument
return partial
end
end
local sha2for51 = {
sha224 = function (text) return sha256ext(224, text) end, -- SHA-224
sha256 = function (text) return sha256ext(256, text) end, -- SHA-256
sha384 = function (text) return sha512ext(384, text) end, -- SHA-384
sha512 = function (text) return sha512ext(512, text) end, -- SHA-512
sha512_224 = function (text) return sha512ext(224, text) end, -- SHA-512/224
sha512_256 = function (text) return sha512ext(256, text) end, -- SHA-512/256
}
return sha2for51
File sha2for51_test.lua
--------------------------------------------------------------------------------
-- TESTS
--------------------------------------------------------------------------------
local sha2 = require"sha2for51"
local function test_sha256()
local sha256 = sha2.sha256
-- some test strings
assert(sha256("The quick brown fox jumps over the lazy dog") == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592")
assert(sha256("The quick brown fox jumps over the lazy cog") == "e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be")
assert(sha256("abc") == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
assert(sha256("123456") == "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92")
assert(sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") == "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1")
assert(sha256("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") == "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1")
-- chunk-by-chunk loading: sha256("string") == sha256()("st")("ri")("ng")()
local append_next_chunk = sha256() -- create a private closure for calculating digest of single string
append_next_chunk("The quick brown fox")
append_next_chunk(" jumps ")
append_next_chunk("") -- chunk may be empty string
append_next_chunk("over the lazy dog")
assert(append_next_chunk() == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") -- asking for final result (invocation without an argument)
assert(append_next_chunk() == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") -- you can ask the same result multiple times if needed
-- append_next_chunk("more text") will fail here: no more chunks are allowed after receiving the result, the closure is useless now, let it be GC-ed
assert(not pcall(append_next_chunk, "more text"))
-- one-liner is possible due to "append_next_chunk(chunk)" returns the function "append_next_chunk"
assert(sha256()("The quick brown fox")(" jumps ")("")("over the lazy dog")() == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592")
-- empty string
assert(sha256("") == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
assert(sha256()() == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
-- computations of different strings don't interfere with each other
local chunk_for_digits = sha256()
chunk_for_digits("123")
local chunk_for_fox = sha256()
chunk_for_fox("The quick brown fox jumps ")
chunk_for_digits("45")
chunk_for_fox("over the lazy dog")
chunk_for_digits("6")
assert(chunk_for_digits() == "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92")
assert(chunk_for_fox() == "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592")
-- "00...0\n"
for i, dgst in pairs{ -- from 50 to 70 zeroes
[50] = "9660acb8046abf46cf27280e61abd174ebac98ad6855e093772b78df85523129",
[51] = "31e1c552b357ace9bcb924691799a3c0d3aa10d8b428d9de28a278e3c79ecb7b",
[52] = "0be5c4bcb6f47e30c13515594dbef4faa3a6485af67c177179fee8b33cd4f2a0",
[53] = "d368c7f6038c1743bdbfe6a9c3a72d4e6916aa219ed8d559766c9e8f9845f3b8",
[54] = "7080a4aa6ff030ae152fe610a62ee29464f92afeb176474551a69d35aab154a0",
[55] = "149c1cda81fa9359c0c2a5e405ca972986f1d53e05f6282871dd1581046b3f44",
[56] = "eb2d4d41948ce546c8adff07ee97342070c5b89789f616a33efe52c7d3ec73d4",
[57] = "c831db596ccbbf248023461b1c05d3ae084bcc79bcb2626c5ec179fb34371f2a",
[58] = "1345b8a930737b1069bbf9b891ce095850f6cdba6e25874ea526a2ccb611fe46",
[59] = "380ad21e466885fae080ceeada75ac04944687e626e161c0b24e91af3eec2def",
[60] = "b9ab06fa30ef8531c5eee11651aa86f8279a245e0a3c29bf6228c59475cc610a",
[61] = "bcc187de6605d9e11a0cc6edf02b67fb651fe1779ec59438788093d8e376c07c",
[62] = "ae0b3681157b83b34de8591d2453915e40c3105ae79434e241d82d4035218e01",
[63] = "68a27b4735f6806fb5983c1805a23797aa93ea06e0ebcb6daada2ea1ab5a05af",
[64] = "827d096d92f3deeaa0e8070d79f45beb176768e57a958a1cd325f5f4b754b048",
[65] = "6c7bd8ec0fe9b4e05a2d27dd5e41a8687a9716a2e8926bdfa141266b12942ec1",
[66] = "2f4b4c41017a2ddd1cc8cd75478a82e9452e445d4242f09782535376d6f4ba50",
[67] = "b777b86e005807a446ead00986fcbf3bdd6c022524deabf017eeb3f0c30b6eed",
[68] = "777da331f60c793f582e4ca33223778218ddfd241981f15be5886171fb8301b5",
[69] = "06ed0c4cbf7d2b38de5f01eab2d2cd552d9cb87f97b714b96bb7a9d1b6117c6d",
[70] = "e82223344d5f3c024514cfbe6d478b5df98bb878f34d7a07e7b064fa7fa91946"
} do
assert(sha256(("0"):rep(i).."\n") == dgst)
end
-- "aa...a"
assert(sha256(("a"):rep(55)) == "9f4390f8d30c2dd92ec9f095b65e2b9ae9b0a925a5258e241c9f1e910f734318")
assert(sha256(("a"):rep(56)) == "b35439a4ac6f0948b6d6f9e3c6af0f5f590ce20f1bde7090ef7970686ec6738a")
-- "aa...a\n" in chunk-by-chunk mode
local next_chunk = sha256()
for i = 1, 65 do
next_chunk("a")
end
next_chunk("\n")
assert(next_chunk() == "574883a9977284a46845620eaa55c3fa8209eaa3ebffe44774b6eb2dba2cb325")
local function split_and_calculate_sha256(s, len) -- split string s in chunks of length len
local next_chunk = sha256()
for idx = 1, #s, len do
next_chunk(s:sub(idx, idx + len - 1))
end
return next_chunk()
end
-- "00...0\n00...0\n...00...0\n" (80 lines of 80 zeroes each) in chunk-by-chunk mode with different chunk lengths
local s = (("0"):rep(80).."\n"):rep(80)
assert(split_and_calculate_sha256(s, 1) == "736c7a8b17e2cfd44a3267a844db1a8a3e8988d739e3e95b8dd32678fb599139")
assert(split_and_calculate_sha256(s, 2) == "736c7a8b17e2cfd44a3267a844db1a8a3e8988d739e3e95b8dd32678fb599139")
assert(split_and_calculate_sha256(s, 7) == "736c7a8b17e2cfd44a3267a844db1a8a3e8988d739e3e95b8dd32678fb599139")
assert(split_and_calculate_sha256(s, 70) == "736c7a8b17e2cfd44a3267a844db1a8a3e8988d739e3e95b8dd32678fb599139")
end
local function test_sha512()
local sha512 = sha2.sha512
assert(sha512("abc") == "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
assert(sha512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") ==
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909")
-- "aa...a"
for i, dgst in pairs{ -- from 109 to 116 letters "a"
[109] = "0cda6b04d9466bb7f3995c16732e1347f29c23a64fe0b085fadba0995644cc5aa71587423c274c10e09518310c5f866cfaceb229fabb574219f12182eb114182",
[110] = "c825949632e509824543f7eaf159fb6041722fce3c1cdcbb613b3d37ff107c519417baac32f8e74fe29d7f4823bf6886956603dca5354a6ed6e4a542e06b7d28",
[111] = "fa9121c7b32b9e01733d034cfc78cbf67f926c7ed83e82200ef86818196921760b4beff48404df811b953828274461673c68d04e297b0eb7b2b4d60fc6b566a2",
[112] = "c01d080efd492776a1c43bd23dd99d0a2e626d481e16782e75d54c2503b5dc32bd05f0f1ba33e568b88fd2d970929b719ecbb152f58f130a407c8830604b70ca",
[113] = "55ddd8ac210a6e18ba1ee055af84c966e0dbff091c43580ae1be703bdb85da31acf6948cf5bd90c55a20e5450f22fb89bd8d0085e39f85a86cc46abbca75e24d",
[114] = "5e9eb0e4b270d086e77eeaf3ce8b1cfc615031b8c463dc34f5c139786f274f22accb4d89e8f40d1a0c2acc84c4dc0f2bab390a9d9495493bd617ed004271bb64",
[115] = "eaa30f93760743ac7d0a6cb8ed5ef3b30c59097bc44d0ec337344301deba9fb92b20c488d55de415f6aaed0df4925b42894b81d2e1cde89d91ec7f6cc67262b4",
[116] = "a8bff469314a1ce0c990bb3fd539d92accb6249cc674b559bc9d3898b7a126fee597197fa42c971443470053c7d7f54b09371a59b0f7af87b1917c5347e8f8e0",
} do
assert(sha512(("a"):rep(i)) == dgst)
end
end
local function all_tests_sha2()
test_sha256()
assert(sha2.sha224"abc" == "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7")
assert(sha2.sha224"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" == "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525")
test_sha512()
assert(sha2.sha384"abc" == "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7")
assert(sha2.sha384"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" == "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039")
assert(sha2.sha512_224"abc" == "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa")
assert(sha2.sha512_224"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" == "23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9")
assert(sha2.sha512_256"abc" == "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23")
assert(sha2.sha512_256"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" == "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a")
print"All tests passed"
end
all_tests_sha2()
local function benchmark()
print("Benchmarking (calculating SHA512 of 1MByte string of letters 'a')...")
local time_intervals = {}
local length = 2^20
local part = ("a"):rep(2^12)
local N = length/#part
local result
local k = 2
for j = 1, 2*k-1 do
local clk0 = os.clock()
local x = sha2.sha512()
for j = 1, N do
x(part)
end
result = x()
time_intervals[j] = os.clock() - clk0
end
--print("Result = "..result)
-- get median time
table.sort(time_intervals)
print('CPU seconds:', time_intervals[k])
end
benchmark() -- about 15 seconds per megabyte

how do you take a decimal to a fraction in lua with no added libraries?

i am working on a calculator running in pure lua but i need help with making the out put decimals in to fractions
This solution uses continued fraction to exactly restore fractions with denominator up to 107
local function to_frac(num)
local W = math.floor(num)
local F = num - W
local pn, n, N = 0, 1
local pd, d, D = 1, 0
local x, err, q, Q
repeat
x = x and 1 / (x - q) or F
q, Q = math.floor(x), math.floor(x + 0.5)
pn, n, N = n, q*n + pn, Q*n + pn
pd, d, D = d, q*d + pd, Q*d + pd
err = F - N/D
until math.abs(err) < 1e-15
return N + D*W, D, err
end
local function print_frac(numer,denom)
print(string.format("%.14g/%d = %d/%d + %g", numer, denom, to_frac(numer/denom)))
end
print_frac(1, 4) --> 1/4 = 1/4 + 0
print_frac(12, 8) --> 12/8 = 3/2 + 0
print_frac(4, 2) --> 4/2 = 2/1 + 0
print_frac(16, 11) --> 16/11 = 16/11 + 5.55112e-17
print_frac(1, 13) --> 1/13 = 1/13 + 0
print_frac(math.sqrt(3), 1) --> 1.7320508075689/1 = 50843527/29354524 + -4.44089e-16
print_frac(math.pi, 1) --> 3.1415926535898/1 = 80143857/25510582 + 4.44089e-16
print_frac(0, 3) --> 0/3 = 0/1 + 0
print_frac(-10, 3) --> -10/3 = -10/3 + -1.11022e-16
This is not possible. You need a class which stores fractions for that.
You can achieve an approximate solution. It works nicely for things that can be expressed as fraction and blows up for everything else
local function gcd(a, b)
while a ~= 0 do
a, b = b%a, a;
end
return b;
end
local function round(a)
return math.floor(a+.5)
end
function to_frac(num)
local integer = math.floor(num)
local decimal = num - integer
if decimal == 0 then
return num, 1.0, 0.0
end
local prec = 1000000000
local gcd_ = gcd(round(decimal*prec), prec)
local numer = math.floor((integer*prec + round(decimal*prec))/gcd_)
local denom = math.floor(prec/gcd_)
local err = numer/denom - num
return numer, denom, err
end
function print_frac(numer,denom)
print(string.format("%d/%d = %d/%d + %g", numer, denom, to_frac(numer/denom)))
end
print_frac(1,4)
print_frac(12,8)
print_frac(4,2)
print_frac(16,11)
print_frac(1,13)
Output:
1/4 = 1/4 + 0
12/8 = 3/2 + 0
4/2 = 2/1 + 0
16/11 = 290909091/200000000 + 4.54546e-10
1/13 = 76923077/1000000000 + 7.69231e-11

Runtime of while loop pseudocode

I have a pseudocode which I'm trying to make a detailed analysis, analyze runtime, and asymptotic analysis:
sum = 0
i = 1
while (i ≤ n){
sum = sum + i
i = 2i
}
return sum
My assignment requires that I write the cost/runtime for every line, add these together, and find a Big-Oh notation for the runtime. My analysis looks like this for the moment:
sum = 0 1
long i = 1 1
while (i ≤ n){ log n + 1
sum = sum + i n log n
i = 2i n log n
}
return sum 1
=> 2 n log n + log n + 4 O(n log n)
is this correct ? Also: should I use n^2 on the while loop instead ?
Because of integer arithmetic, the runtime is
O(floor(ln(n))+1) = O(ln(n)).
Let's step through your pseudocode. Consider the case that n = 5.
iteration# i ln(i) n
-------------------------
1 1 0 5
2 2 1 5
3 4 2 5
By inspection we see that
iteration# = ln(i)+1
So in summary:
sum = 0 // O(1)
i = 1 // O(1)
while (i ≤ n) { // O(floor(ln(n))+1)
sum = sum + i // 1 flop + 1 mem op = O(1)
i = 2i // 1 flop + 1 mem op = O(1)
}
return sum // 1 mem op = O(1)

Resources