I need to write my own recursive function in ML that somehow uses ord to convert a string of numbers to integer type. I can use helper functions, but apparently I should be able to do this without using one (according to my professor).
I can assume that the input is valid, and is a positive integer (in string type of course).
So, the call str2int ("1234") should output 1234: int
I assume I will need to use explode and implode at some point since ord operates on characters, and my input is a string. Any direction would be greatly appreciated.
Given that you asked, I guess I can ruin all the fun for you. This will solve your problem, but ironically, it won't help you.
Well, the ordinal number for the character #'0' is 48. So, this means that if you subtract of any ordinal representing a digit the number 48 you get its decimal value. For instance
ord(#"9") - 48
Yields 9.
So, a function that takes a given character representing a number from 0-9 and turns it into the corresponding decimal is:
fun charToInt(c) = ord(c) - 48
Supposing you had a string of numbers like "2014". Then you can first explode the string into list of characters and then map every character to its corresponding decimal.
For instance
val num = "2014"
val digits = map charToInt (explode num)
The explode function is a helper function that takes a string and turn it into a list of characters.
And now digits would be a list of integers representing the decimal numbers [2,0,1,4];
Then, all you need is to apply powers of 10 to obtain the final integer.
2 * 10 ^ 3 = 2000
0 * 10 ^ 2 = 0
1 * 10 ^ 1 = 10
4 * 10 ^ 0 = 4
The result would be 2000 + 0 + 10 + 4 = 2014
You could define a helper function charsToInt that processes the digits in the string from left to right.
At each step it converts the leftmost digit c into a number and does addition with the 10x-multiple of n (which is the intermediary sum of all previously parsed digits) ...
fun charsToInt ([], n) = n
| charsToInt (c :: cs, n) = charsToInt (cs, 10*n + ord c - 48)
val n = charsToInt (explode "1024", 0)
Gives you: val n = 1024 : int
As you see the trick is to pass the intermediary result down to the next step at each recursive call. This is a very common technique when dealing with these kind of problems.
Here's what I came up with:
fun pow10 n =
if n = 0 then 1 else 10*pow10(n-1);
fun str2help (L,n) =
if null L then 0
else (ord(hd L)-48) * pow10(n) + str2help(tl L, n-1);
fun str2int (string) =
str2help(explode string, size string -1);
str2int ("1234");
This gives me the correct result, though is clearly not the easiest way to get there.
Related
I don't even know if something like this is possible, but:
Let us say we have three numbers:
A = 6
B = 7.5
C = 24
I would like to find a few evenly spaced common multiples of these numbers between 0 and 2.
So the requirement is: one_of_these_numbers / common_multiple = an_integer (or almost an integer with a particular tolerance)
For example, a good result would be [0.1 , 0.5 , 1 , 1.5]
I have no idea if this is possible, because one can not iterate through a range of floats, but is there a smart way to do it?
I am using python, but a solution could be represented in any language of your preference.
Thank you for your help!
While I was writing my question, I actually came up with an idea for the solution.
To find common divisors using code, we have to work with integers.
My solution is to multiply all numbers by a factor = 1, 10, 100, ...
so that we can act as if they are integers, find their integer common divisors, and then redivide them by the factor to get a result.
Better explained in code:
a = 6
b = 7.5
c = 24
# Find a few possible divisors between 0 and 2 so that all numbers are divisible
by div.
# We define a function that finds all divisors in a range of numbers, supposing
all numbers are integers.
def find_common_divisors(numbers, range_start, range_end):
results = []
for i in range(range_start + 1, range_end + 1):
if all([e % i == 0 for e in numbers]):
results.append(i)
return results
def main():
nums = [a, b, c]
range_start = 0
range_end = 2
factor = 1
results = [1]
while factor < 11:
nums_i = [e * factor for e in nums]
range_end_i = range_end * factor
results += [e / factor for e in find_common_divisors(nums_i, range_start, range_end_i)]
factor *= 10
print(sorted(set(results)))
if __name__ == '__main__':
main()
For these particular numbers, I get the output:
[0.1, 0.3, 0.5, 1, 1.5]
If we need more results, we can adjust while factor < 11: to a higher number than 11 like 101.
I am curious to see if I made any mistake in my code.
Happy to hear some feedback.
Thank you!
I'm trying to code this formula in prolog :
"str" is input number as a string
"base" is the base of the input number.
Result is,
(base)^0 * str[len-1] + (base)^1 * str[len-2] + (base)^2 * str[len-3] + ...
I'm new to prolog and I have this right now:
calc([],_,0):- !.
calc([H|T],Base,Res):-
length([H|T],Long),
Long >= 0,
Size is Long - 1,
power(Base , Size, Res),
Res1 is Res * H,
calc(T,Base,Res1).
but it doesn't work properly I spent yesterday trying to solve the problem but with no success.
Any help is appreciated :) .
You can do something like this:
value(String, Base, Value) :-
string_chars(String, Digits),
value(Digits, Base, 0, Value).
value([], _, Value, Value).
value([Digit|Digits], Base, Accumulator, Value) :-
atoi(Digit, Number),
NewAccumulator is Base*Accumulator + Number,
value(Digits, Base, NewAccumulator, Value).
atoi(Char, Int) :- % convert ASCII code to integer
char_code(Char, Code) ,
Int is Code - 48.
The predefined predicate string_chars converts a string into a list of chars:
?- string_chars("1101", Chars).
Chars = ['1', '1', '0', '1'].
The predicate atoi converts a character representing a digit into a corresponding integer:
?- atoi('3', Integer).
Integer = 3.
Supposing that [1,1,0,1] is a list of integers (representing a number in base 2), its corresponding value in base 10 can be computed as following:
Digit Accumulator
- 0
1 2 x 0 + 1 = 1
1 2 x 1 + 1 = 3
0 2 x 3 + 0 = 6
1 2 x 6 + 1 = 13
Here are some examples:
?- value("1101", 2, V).
V = 13.
?- value("1201", 3, V).
V = 46.
Alternative solution Suppossing that you already have a list of integers representing the digits of a number, the solution is even simpler:
value_integers(Digits, Base, Value) :-
value_integers(Digits, Base, 0, Value).
value_integers([], _, Value, Value).
value_integers([Digit|Digits], Base, Accumulator, Value) :-
NewAccumulator is Base*Accumulator + Digit,
value_integers(Digits, Base, NewAccumulator, Value).
Here are some examples:
?- value_integers([1,1,0,1], 2, Value).
Value = 13.
?- value_integers([1,2,0,1], 3, Value).
Value = 46.
?- value_integers([1,2,0,1], 10, Value).
Value = 1201.
I have the following data:
y-n-y-y-n-n-n
This repeats infinitely, such as:
y-n-y-y-n-n-n-y-n-y-y-n-n-n-y-n-y-y-n-n-n...
I have 5 "x".
"x" only sticks with "y".
Meaning, if I distribute x on the loop above, it will be:
y-n-y-y-n-n-n-y-n-y-y-n-n-n
x---x-x-----x-x
I want to count how many of the loop's element I needed to use to spread 5 x across, and the answer is 10.
How do I calculate it with a formula?
I presume what you're saying is that you need to process the first 10 elements of the infinite list to get 5 Y's, which match/stick with the 5 X's you have.
y-n-y-y-n-n-n-y-n-y-y-n-n-n-y-n-y-y-n-n-n...
x-_-x-x-_-_-_-x-_-x
^
L____ 10 elements read from the infinite list to place the 5 x's.
I also presume that your question is: given an input of 5 Xs, what is the number of elements you need to process in the infinite list to match those 5 Xs.
You could calculate it with a loop like the following pseudo-code:
iElementsMatchedCounter = 0
iXsMatchedCounter = 0
iXLimit = 5
strElement = ""
if (InfiniteList.IsEmpty() == false)
{
do
{
strElement = InfiniteList.ReadNextElement()
if (strElement == "y")
{
iXsMatchedCounter += 1
}
iElementsMatchedCounter += 1
} while ( (InfiniteList.IsEndReached() == false) AND (iXsMatchedCounter < iXLimit) )
}
if (iXsMatchedCounter = iXLimit)
then Print(iElementsMatchedCounter)
else Print("End of list reached before all X's were matched!")
The drawback of the above approach is that you are actually reading the infinite list, which might not be preferable.
Instead, given you know your list is an infinitely repeating sequence of the same elements y-n-y-y-n-n-n, you don't even need to loop through the entire list, but just operate on the sub-list y-n-y-y-n-n-n. The following algorithm describes how:
Given your starting input:
iNumberOfXs = 5 (you have 5 Xs to match)
iNumberOfYsInSubList = 3
(you have 3 Ys in the sub-list, the total list repeats infinitely)
iLengthOfSubList = 7 (you have 7 elements in the sub-list
y-n-y-y-n-n-n)
We then have intermediate results which are calculated:
iQuotient
iPartialLengthOfList
iPendingXs
iPendingLengthOfList
iResult
The following steps should give the result:
Divide the iNumberOfXs by iNumberOfYsInSubList. Here, this gives us 5/3 = 1.666....
Discard the remainder of the result (the 0.666...), so you're left with 1 as iQuotient. This is the number of complete sub-lists you have to iterate.
Multiply this quotient 1 with iLengthOfSubList, giving you 1*7=7 as iPartialLengthOfList. This is the partial sum of the result, and is the number of elements in the complete sub-lists you iterate.
Also multiply the quotient with iNumberOfYsInSubList, and subtract this product from iNumberOfXs, i.e. iNumberOfXs - (iQuotient * iNumberOfYsInSubList) = 5 - (1 * 3) = 2. Save this value 2 as iPendingXs, which is the number of as-yet unmatched X's.
Note that iPendingXs will always be less than iLengthOfSubList (i.e. it is a modulo, iPendingXs = iNumberOfXs MODULO iNumberOfYsInSubList).
Now you have the trivial problem of matching 2 X's (i.e. the value of iPendingXs calculated above) in the sub-list of y-n-y-y-n-n-n.
The pending items to match (counted as iPendingLengthOfList) is:
Equal to iPendingXs if iPendingXs is 0 or 1
Equal to iPendingXs + 1 otherwise (i.e. if iPendingXs is greater than 1)
In this case, iPendingLengthOfList = 3, because iPendingXs is greater than 1.
The sum of iPartialLengthOfList (7) and iPendingLengthOfList (3) is the answer, namely 10.
In general, if your sub-list y-n-y-y-n-n-n is not pre-defined, then you cannot hard-code the rule in step 6, but will instead have to loop through only the sub-list once to count the Ys and elements, similar to the pseudo-code given above.
When it comes to actual code, you can use integer division and modulo arithmetic to quickly to the operations in steps 2 and 4 respectively.
iQuotient = iNumberOfXs / iNumberOfYsInSubList // COMMENT: here integer division automatically drops the remainder
iPartialLengthOfList = iQuotient * iLengthOfSubList
iPendingXs = iNumberOfXs - (iQuotient * iNumberOfYsInSubList)
// COMMENT: can use modulo arithmetic like the following to calculate iPendingXs
// iPendingXs = iNumberOfXs % iNumberOfYsInSubList
// The following IF statement assumes the sub-list to be y-n-y-y-n-n-n
if (iPendingXs > 1)
then iPendingLengthOfList = iPendingXs + 1
else iPendingLengthOfList = iPendingXs
iResult = iPartialLengthOfList + iPendingLengthOfList
I am trying to make a function to round a floating point number to a defined length of digits. What I have come up with so far is this:
import Numeric;
digs :: Integral x => x -> [x] <br>
digs 0 = [] <br>
digs x = digs (x `div` 10) ++ [x `mod` 10]
roundTo x t = let d = length $ digs $ round x <br>
roundToMachine x t = (fromInteger $ round $ x * 10^^t) * 10^^(-t)
in roundToMachine x (t - d)
I am using the digs function to determine the number of digits before the comma to optimize the input value (i.e. move everything past the comma, so 1.234 becomes 0.1234 * 10^1)
The roundTo function seems to work for most input, however for some inputs I get strange results, e.g. roundTo 1.0014 4 produces 1.0010000000000001 instead of 1.001.
The problem in this example is caused by calculating 1001 * 1.0e-3 (which returns 1.0010000000000001)
Is this simply a problem in the number representation of Haskell I have to live with or is there a better way to round a floating point number to a specific length of digits?
I realise this question was posted almost 2 years back, but I thought I'd have a go at an answer that didn't require a string conversion.
-- x : number you want rounded, n : number of decimal places you want...
truncate' :: Double -> Int -> Double
truncate' x n = (fromIntegral (floor (x * t))) / t
where t = 10^n
-- How to answer your problem...
λ truncate' 1.0014 3
1.001
-- 2 digits of a recurring decimal please...
λ truncate' (1/3) 2
0.33
-- How about 6 digits of pi?
λ truncate' pi 6
3.141592
I've not tested it thoroughly, so if you find numbers this doesn't work for let me know!
This isn't a haskell problem as much as a floating point problem. Since each floating point number is implemented in a finite number of bits, there exist numbers that can't be represented completely accurately. You can also see this by calculating 0.1 + 0.2, which awkwardly returns 0.30000000000000004 instead of 0.3. This has to do with how floating point numbers are implemented for your language and hardware architecture.
The solution is to continue using your roundTo function for doing computation (it's as accurate as you'll get without special libraries), but if you want to print it to the screen then you should use string formatting such as the Text.Printf.printf function. You can specify the number of digits to round to when converting to a string with something like
import Text.Printf
roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr n f = printf ("%0." ++ show n ++ "f") f
But as I mentioned, this will return a string rather than a number.
EDIT:
A better way might be
roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr n f = printf (printf "%%0.%df" n) f
but I haven't benchmarked to see which is actually faster. Both will work exactly the same though.
EDIT 2:
As #augustss has pointed out, you can do it even easier with just
roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr = printf "%0.*f"
which uses a formatting rule that I was previously unaware of.
I also think that avoiding string conversion is the way to go; however, I would modify the previous post (from schanq) to use round instead of floor:
round' :: Double -> Integer -> Double
round' num sg = (fromIntegral . round $ num * f) / f
where f = 10^sg
> round' 4 3.99999
4.0
> round' 4 4.00001
4.0
For ex.
double size = 10.35;
i should get
value = 1035;
exponent = -2;
so when i re calculate i will get 10.35.
i.e 1035 * 10^-2 = 10.35;
Please help me.
Thanks in advance
In general this is not possible since the fractional part of a double is stored in powers-of-2, and might or might not match powers-of-10.
For example: When looking at powers-of-2 vs powers-of-3: Just like 1/2 == 2^-1 == 5 * 10^-1 has a match, 1/3 == 3^-1 == ?? does not have a match.
However, you can approximate it.
It would have an answer if you would ask for powers-of-2. In that case you can just look at the double representation (see IEEE-754 here) and extract the right bits.
Very simplistically (in C#):
double size = 10.36;
int power = 0;
while (size != (int)size)
{
size *= 10.0;
power--;
}
Console.WriteLine("{0} * 10 to the {1}", size, power);
Though I'm sure with a bit more thought a more elegant solution can be found.
This doesn't go the other way where you've got a large number (103600 say) and want to get the smallest value to some power (1036 * 10^2).
I had to do something very similar. Here's a solution in Python (it hasn't been tested very well):
def normalize(value, fdigits=2):
"""
Convert a string representing a numerical value to value-digit/exponent form.
Round the fractional portion to the given number of digits.
value the value (string)
fdigits the number of digits to which to round the fractional
portion
"""
# if empty string, return error
if not value:
return None
# split value by decimal
v = value.split('.')
# if too many decimals, return error
if len(v) > 2:
return None
# add empty string for fractional portion if missing
elif len(v) == 1:
v.append('')
# assign whole and fractional portions
(w, f) = v
# pad fractional portion up to number of significant digits if necessary
if len(f) < fdigits:
f += ('0' * (fdigits - len(f)))
# if the number of digits in the fractional portion exceeds the
# number of digits allowed by fdigits
elif len(f) > fdigits:
# convert both portions to integers; use '0' for whole portion if missing
(wi, fi) = (int(w or '0'), int(f[:fdigits]))
# round up if first insignificant digit is gteq 5
if int(f[fdigits]) >= 5:
fi += 1
# roll whole value up if fractional portion rounds to a whole
if len(str(fi)) > fdigits:
wi += 1
fi = 0
# replace the whole and fractional strings
(w, f) = (str(wi), ("%0" + str(fdigits) + "d") % fi)
# derive value digits and exponent
n = w.lstrip() + f
l = len(n)
x = -fdigits
n = n.rstrip('0')
x += (l - len(n))
# return value digits and exponent
return (int(n), x)