Is there a way to assert that the first digit (most significant) of number is a particular digit? - z3

I would like to assert that the most significant digit of a number is a particular value, but I don't actually know the length of the number. If it was the least significant digit, I know I could use the python mod (%) to check for it. But with an unknown number of digits, I'm unsure of how I could check this in z3.
For example, I may know that the left most digit is a 9, such as 9x, or 9xx, or 9xxx etc.
Thanks so much in advance

The generic way to do this would be to convert to a string and check that the first character matches:
from z3 import *
s = Solver()
n = Int('n')
s.add(SubString(IntToStr(n), 0, 1) == "9")
r = s.check()
if r == sat:
m = s.model()
print("n =", m[n])
else:
print("Solver said:", r)
This prints:
n = 9
Note that IntToStr expects its argument to be non-negative, so if you need to support negative numbers, you'll have to write extra code to accommodate for that. See https://smtlib.cs.uiowa.edu/theories-UnicodeStrings.shtml for details.
Aside While this will accomplish what you want in its generality, it may not be the most efficient way to encode this constraint. Since it goes through strings, the constraints generated might cause performance issues. If you have an upper limit on your number, it might be more efficient to code it explicitly. For instance, if you know your number is less than a 1000, I'd code it as (pseudocode):
n == 9 || n >= 90 && n <= 99 || n >= 900 && n <= 999
etc. until you have the range you needed covered. This would lead to much simpler constraints and perform a lot better in general. Note that this'll work even if you don't know the exact length, but have an upper bound on it. But of course, it all depends on what you are trying to achieve and what else you know about the number itself.

Related

Finding the number of digits in a number restricted number of tools since I am a Python beginner

def digits(n):
total=0
for i in range(0,n):
if n/(10**(i))<1 and n/(10**(i-1))=>1:
total+=i
else:
total+=0
return total
I want to find the number of digits in 13 so I do the below
print digits(13)
it gives me $\0$ for every number I input into the function.
there's nothing wrong with what I've written as far as I can see:
if a number has say 4 digits say 1234 then dividing by 10^4 will make it less than 1: 0.1234 and dividing by 10^3 will make it 1.234
and by 10^3 will make it 1.234>1. when i satisfies BOTH conditions you know you have the correct number of digits.
what's failing here? Please can you advise me on the specific method I've tried
and not a different one?
Remember for every n there can only be one i which satisfies that condition.
so when you add i to the total there will only be i added so total returning total will give you i
your loop makes no sense at all. It goes from 0 to exact number - not what you want.
It looks like python, so grab a solution that uses string:
def digits(n):
return len(str(int(n))) # make sure that it's integer, than conver to string and return number of characters == number of digits
EDIT:
If you REALLY want to use a loop to count number of digits, you can do this this way:
def digits(n):
i = 0
while (n > 1):
n = n / 10
++i
return i
EDIT2:
since you really want to make your solution work, here is your problem. Provided, that you call your function like digits(5), 5 is of type integer, so your division is integer-based. That means, that 6/100 = 0, not 0.06.
def digits(n):
for i in range(0,n):
if n/float(10**(i))<1 and n/float(10**(i-1))=>1:
return i # we don't need to check anything else, this is the solution
return null # we don't the answer. This should not happen, but still, nice to put it here. Throwing an exception would be even better
I fixed it. Thanks for your input though :)
def digits(n):
for i in range(0,n):
if n/(10**(i))<1 and n/(10**(i-1))>=1:
return i

Calculating ISIN checksum

HI I know there have been may question about this here but I wasn't able to find a detailed enough answer, Wikipedia has two examples of ISIN and how is their checksum calculated.
The part of calculation that I'm struggling with is
Multiply the group containing the rightmost character
The way I understand this statement is:
Iterate through each character from right to left
once you stumble upon a character rather than digit record its position
if the position is an even number double all numeric values in even position
if the position is an odd number double all numeric values in odd position
My understanding has to be wrong because there are at least two problems:
Every ISIN starts with two character country code so position of rightmost character is always the first character
If you omit the first two characters then there is no explanation as to what to do with ISINs that are made up of all numbers (except for first two characters)
Note
isin.org contains even less information on verifying ISINs, they even use the same example as Wikipedia.
I agree with you; the definition on Wikipedia is not the clearest I have seen.
There's a piece of text just before the two examples that explains when one or the other algorithm should be used:
Since the NSIN element can be any alpha numeric sequence (9 characters), an odd number of letters will result in an even number of digits and an even number of letters will result in an odd number of digits. For an odd number of digits, the approach in the first example is used. For an even number of digits, the approach in the second example is used
The NSIN is identical to the ISIN, excluding the first two letters and the last digit; so if the ISIN is US0378331005 the NSIN is 037833100.
So, if you want to verify the checksum digit of US0378331005, you'll have to use the "first algorithm" because there are 9 digits in the NSIN. Conversely, if you want to check AU0000XVGZA3 you're going to use the "second algorithm" because the NSIN contains 4 digits.
As to the "first" and "second" algorithms, they're identical, with the only exception that in the former you'll multiply by 2 the group of odd digits, whereas in the latter you'll multiply by 2 the group of even digits.
Now, the good news is, you can get away without this overcomplicated algorithm.
You can, instead:
Take the ISIN except the last digit (which you'll want to verify)
Convert all letters to numbers, so to obtain a list of digits
Reverse the list of digits
All the digits in an odd position are doubled and their digits summed again if the result is >= 10
All the digits in an even position are taken as they are
Sum all the digits, take the modulo, subtract the result from 0 and take the absolute value
The only tricky step is #4. Let's clarify it with a mini-example.
Suppose the digits in an odd position are 4, 0, 7.
You'll double them and get: 8, 0, 14.
8 is not >= 10, so we take it as it is. Ditto for 0. 14 is >= 10, so we sum its digits again: 1+4=5.
The result of step #4 in this mini-example is, therefore: 8, 0, 5.
A minimal, working implementation in Python could look like this:
import string
isin = 'US4581401001'
def digit_sum(n):
return (n // 10) + (n % 10)
alphabet = {letter: value for (value, letter) in
enumerate(''.join(str(n) for n in range(10)) + string.ascii_uppercase)}
isin_to_digits = ''.join(str(d) for d in (alphabet[v] for v in isin[:-1]))
isin_sum = 0
for (i, c) in enumerate(reversed(isin_to_digits), 1):
if i % 2 == 1:
isin_sum += digit_sum(2*int(c))
else:
isin_sum += int(c)
checksum_digit = abs(- isin_sum % 10)
assert int(isin[-1]) == checksum_digit
Or, more crammed, just for functional fun:
checksum_digit = abs( - sum(digit_sum(2*int(c)) if i % 2 == 1 else int(c)
for (i, c) in enumerate(
reversed(''.join(str(d) for d in (alphabet[v] for v in isin[:-1]))), 1)) % 10)

Lua: Rounding numbers and then truncate

Which is the best efficient way to round up a number and then truncate it (remove decimal places after rounding up)?
for example if decimal is above 0.5 (that is, 0.6, 0.7, and so on), I want to round up and then truncate (case 1). Otherwise, I would like to truncate (case 2)
for example:
232.98266601563 => after rounding and truncate = 233 (case 1)
232.49445450000 => after rounding and truncate = 232 (case 2)
232.50000000000 => after rounding and truncate = 232 (case 2)
There is no build-in math.round() function in Lua, but you can do the following:
print(math.floor(a+0.5)).
A trick that is useful for rounding at decimal digits other than whole integers is to pass the value through formatted ASCII text, and use the %f format string to specify the rounding desired. For example
mils = tonumber(string.format("%.3f", exact))
will round the arbitrary value in exact to a multiple of 0.001.
A similar result can be had with scaling before and after using one of math.floor() or math.ceil(), but getting the details right according to your expectations surrounding the treatment of edge cases can be tricky. Not that this isn't an issue with string.format(), but a lot of work has gone into making it produce "expected" results.
Rounding to a multiple of something other than a power of ten will still require scaling, and still has all the tricky edge cases. One approach that is simple to express and has stable behavior is to write
function round(exact, quantum)
local quant,frac = math.modf(exact/quantum)
return quantum * (quant + (frac > 0.5 and 1 or 0))
end
and tweak the exact condition on frac (and possibly the sign of exact) to get the edge cases you wanted.
To also support negative numbers, use this:
function round(x)
return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
end
If your Lua uses double precision IEC-559 (aka IEEE-754) floats, as most do, and your numbers are relatively small (the method is guaranteed to work for inputs between -251 and 251), the following efficient code will perform rounding using your FPU's current rounding mode, which is usually round to nearest, ties to even:
local function round(num)
return num + (2^52 + 2^51) - (2^52 + 2^51)
end
(Note that the numbers in parentheses are calculated at compilation time; they don't affect runtime).
For example, when the FPU is set to round to nearest or even, this unit test prints "All tests passed":
local function testnum(num, expected)
if round(num) ~= expected then
error(("Failure rounding %.17g, expected %.17g, actual %.17g")
:format(num+0, expected+0, round(num)+0))
end
end
local function test(num, expected)
testnum(num, expected)
testnum(-num, -expected)
end
test(0, 0)
test(0.2, 0)
test(0.4, 0)
-- Most rounding algorithms you find on the net, including Ola M's answer,
-- fail this one:
test(0.49999999999999994, 0)
-- Ties are rounded to the nearest even number, rather than always up:
test(0.5, 0)
test(0.5000000000000001, 1)
test(1.4999999999999998, 1)
test(1.5, 2)
test(2.5, 2)
test(3.5, 4)
test(2^51-0.5, 2^51)
test(2^51-0.75, 2^51-1)
test(2^51-1.25, 2^51-1)
test(2^51-1.5, 2^51-2)
print("All tests passed")
Here's another (less efficient, of course) algorithm that performs the same FPU rounding but works for all numbers:
local function round(num)
local ofs = 2^52
if math.abs(num) > ofs then
return num
end
return num < 0 and num - ofs + ofs or num + ofs - ofs
end
Here's one to round to an arbitrary number of digits (0 if not defined):
function round(x, n)
n = math.pow(10, n or 0)
x = x * n
if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
return x / n
end
For bad rounding (cutting the end off):
function round(number)
return number - (number % 1)
end
Well, if you want, you can expand this for good rounding.
function round(number)
if (number - (number % 0.1)) - (number - (number % 1)) < 0.5 then
number = number - (number % 1)
else
number = (number - (number % 1)) + 1
end
return number
end
print(round(3.1))
print(round(math.pi))
print(round(42))
print(round(4.5))
print(round(4.6))
Expected results:
3, 3, 42, 5, 5
I like the response above by RBerteig: mils = tonumber(string.format("%.3f", exact)).
Expanded it to a function call and added a precision value.
function round(number, precision)
local fmtStr = string.format('%%0.%sf',precision)
number = string.format(fmtStr,number)
return number
end
Should be math.ceil(a-0.5) to correctly handle half-integer numbers
Here is a flexible function to round to different number of places. I tested it with negative numbers, big numbers, small numbers, and all manner of edge cases, and it is useful and reliable:
function Round(num, dp)
--[[
round a number to so-many decimal of places, which can be negative,
e.g. -1 places rounds to 10's,
examples
173.2562 rounded to 0 dps is 173.0
173.2562 rounded to 2 dps is 173.26
173.2562 rounded to -1 dps is 170.0
]]--
local mult = 10^(dp or 0)
return math.floor(num * mult + 0.5)/mult
end
For rounding to a given amount of decimals (which can also be negative), I'd suggest the following solution that is combined from the findings already presented as answers, especially the inspiring one given by Pedro Gimeno. I tested a few corner cases I'm interested in but cannot claim that this makes this function 100% reliable:
function round(number, decimals)
local scale = 10^decimals
local c = 2^52 + 2^51
return ((number * scale + c ) - c) / scale
end
These cases illustrate the round-halfway-to-even property (which should be the default on most machines):
assert(round(0.5, 0) == 0)
assert(round(-0.5, 0) == 0)
assert(round(1.5, 0) == 2)
assert(round(-1.5, 0) == -2)
assert(round(0.05, 1) == 0)
assert(round(-0.05, 1) == 0)
assert(round(0.15, 1) == 0.2)
assert(round(-0.15, 1) == -0.2)
I'm aware that my answer doesn't handle the third case of the actual question, but in favor of being IEEE-754 compliant, my approach makes sense. So I'd expect that the results depend on the current rounding mode set in the FPU with FE_TONEAREST being the default. And that's why it seems high likely that after setting FE_TOWARDZERO (however you can do that in Lua) this solution would return exactly the results that were asked for in the question.
Try using math.ceil(number + 0.5) This is according to this Wikipedia page. If I'm correct, this is only rounding positive integers. you need to do math.floor(number - 0.5) for negatives.
If it's useful to anyone, i've hash-ed out a generic version of LUA's logic, but this time for truncate() :
**emphasized text pre-apologize for not knowing lua-syntax, so this is in AWK/lua mixture, but hopefully it should be intuitive enough
-- due to lua-magic alrdy in 2^(52-to-53) zone,
-- has to use a more coarse-grained delta than
-- true IEEE754 double machineepsilon of 2^-52
function trunc_lua(x,s) {
return \
((x*(s=(-1)^(x<-x)) \
- 2^-1 + 2^-50 \ -- can also be written as
\ -- 2^-50-5^0/2
- _LUAMAGIC \ -- if u like symmetric
\ -- code for fun
+ _LUAMAGIC \
) *(s) };
It's essentially the same concept as rounding, but force-processing all inputs in positive-value zone, with a -1*(0.5-delta) offset. The smallest delta i could attain is 2^-52 ~ 2.222e-16.
The lua-magic values must come after all those pre-processing steps, else precision-loss may occur. And finally, restore original sign of input.
The 2 "multiplies" are simply low-overhead sign-flipping. sign-flips 4 times for originally negative values (2 manual flips and round-trip to end of mantissa), while any x >= 0, including that of -0.0, only flips twice. All tertiary function calling, float division, and integer modulus is avoided, with only 1 conditional check for x<0.
usage notes :
(1) doesn't perform checks on input for invalid or malicious payload,
(2) doesn't use quickly check for zero,
(3) doesn't check for extreme inputs that may render this logic moot, and
(4) doesn't attempt to pretty format the value
if not exist math.round
function math.round(x, n)
return tonumber(string.format("%." .. n .. "f", x))
end

if input is nth term in fibonacci series, finding n

in fibonacci series let's assume nth fibonacci term is T. F(n)=T. but i want to write a a program that will take T as input and return n that means which term is it in the series( taken that T always will be a fibonacci number. )i want to find if there lies an efficient way to find it.
The easy way would be to simply start generating Fibonacci numbers until F(i) == T, which has a complexity of O(T) if implemented correctly (read: not recursively). This method also allows you to make sure T is a valid Fibonacci number.
If T is guaranteed to be a valid Fibonacci number, you can use approximation rules:
Formula
It looks complicated, but it's not. The point is: from a certain point on, the ratio of F(i+1)/F(i) becomes a constant value. Since we're not generating Fibonacci Numbers but are merely finding the "index", we can drop most of it and just realize the following:
breakpoint := f(T)
Any f(i) where i > T = f(i-1)*Ratio = f(T) * Ratio^(i-T)
We can get the reverse by simply taking Log(N, R), R being Ratio. By adjusting for the inaccuracy for early numbers, we don't even have to select a breakpoint (if you do: it's ~ correct for i > 17).
The Ratio is, approximately, 1.618034. Taking the log(1.618034) of 6765 (= F(20)), we get a value of 18.3277. The accuracy remains the same for any higher Fibonacci numbers, so simply rounding down and adding 2 gives us the exact Fibonacci "rank" (provided that F(1) = F(2) = 1).
The first step is to implement fib numbers in a non-recursive way such as
fib1=0;fib2=1;
for(i=startIndex;i<stopIndex;i++)
{
if(fib1<fib2)
{
fib1+=fib2;
if(fib1=T) return i;
if(fib1>T) return -1;
}
else
{
fib2+=fib1;
if(fib2=T) return i;
if(fib2>t) return -1;
}
}
Here startIndex would be set to 3 stopIndex would be set to 10000 or so. To cut down in the iteration, you can also select 2 seed number that are sequential fib numbers further down the sequence. startIndex is then set to the next index and do the computation with an appropriate adjustment to the stopIndex. I would suggest breaking the sequence up in several section depending on machine performance and the maximum expected input to minimize the run time.

Lua base converter

I need a base converter function for Lua. I need to convert from base 10 to base 2,3,4,5,6,7,8,9,10,11...36 how can i to this?
In the string to number direction, the function tonumber() takes an optional second argument that specifies the base to use, which may range from 2 to 36 with the obvious meaning for digits in bases greater than 10.
In the number to string direction, this can be done slightly more efficiently than Nikolaus's answer by something like this:
local floor,insert = math.floor, table.insert
function basen(n,b)
n = floor(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % b) + 1
n = floor(n / b)
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,"")
end
This creates fewer garbage strings to collect by using table.concat() instead of repeated calls to the string concatenation operator ... Although it makes little practical difference for strings this small, this idiom should be learned because otherwise building a buffer in a loop with the concatenation operator will actually tend to O(n2) performance while table.concat() has been designed to do substantially better.
There is an unanswered question as to whether it is more efficient to push the digits on a stack in the table t with calls to table.insert(t,1,digit), or to append them to the end with t[#t+1]=digit, followed by a call to string.reverse() to put the digits in the right order. I'll leave the benchmarking to the student. Note that although the code I pasted here does run and appears to get correct answers, there may other opportunities to tune it further.
For example, the common case of base 10 is culled off and handled with the built in tostring() function. But similar culls can be done for bases 8 and 16 which have conversion specifiers for string.format() ("%o" and "%x", respectively).
Also, neither Nikolaus's solution nor mine handle non-integers particularly well. I emphasize that here by forcing the value n to an integer with math.floor() at the beginning.
Correctly converting a general floating point value to any base (even base 10) is fraught with subtleties, which I leave as an exercise to the reader.
you can use a loop to convert an integer into a string containting the required base. for bases below 10 use the following code, if you need a base larger than that you need to add a line that mapps the result of x % base to a character (usign an array for example)
x = 1234
r = ""
base = 8
while x > 0 do
r = "" .. (x % base ) .. r
x = math.floor(x / base)
end
print( r );

Resources