Parse decimal number using Cuerdas in a ClojureScript program - parsing

I am using Cuerdas library in a
ClojureScript program to parse floating point numbers. Sometimes the input from
a user is missing the integral part, like .1 for 0.1. I need to handle this.
But I ran into strange results when comparing the parsed numbers:
(= 0.1 (parse-number "0.1"))
;; => true
(= .1 (parse-number "0.1"))
;; => true
(= 0.1 (parse-number ".1"))
;; => false
(= .1 (parse-number ".1"))
;; => false
The last two results above are surprising to me. When comparing literal number I
get the expected result:
(= 0 .0)
;; => true
The strange behavior is also visible when I just parse the decimal number without integer
part, like here:
(parse-number ".1")
;; => .1
.1
;; => 0.1
I found out that I can use js/parseFloat to get what I want, but I'm curious
what is the reason for this behavior when using Cuerdas? What is this .1 value
and how is it different than 0.1?

parse-number source looked like this:
(defn parse-number
"General purpose function for parse number like
string to number. It works with both integers
and floats."
[s]
(if (nil? s)
#?(:cljs js/NaN :clj Double/NaN)
(if (numeric? s)
(edn/read-string s)
#?(:cljs js/NaN :clj Double/NaN))))
Both ".1" and "0.1" are considered to be numeric? (was implemented in cuerdas by a regex check):
cljs.user=> (def re #"^[+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)([eE][+-]?[0-9]+)?$")
#'cljs.user/re
cljs.user=> (boolean (re-matches re "0.1"))
true
cljs.user=> (boolean (re-matches re ".1"))
true
so they will be read by cljs.reader/read-string.
When reading the string "0.1" the return type is a js/Number, but ".1" is of type cljs.core/Symbol:
cljs.user=> (cljs.reader/read-string ".1")
.1
cljs.user=> (cljs.reader/read-string "0.1")
0.1
cljs.user=> (type (cljs.reader/read-string "0.1"))
#object[Number]
cljs.user=> (type (cljs.reader/read-string ".1"))
cljs.core/Symbol
So although it looks like it correctly parsed the .1 it actually turned it into a symbol. The symbol .1 is not equal to the number .1.
Note that parse-number is no longer available in newer versions of cuerdas because it "is a string manipulation library not a numbers parsing library".

I have some numeric parsing functions that work for both CLJ and CLJS. From the unit tests, we have
The headers:
(ns tst.tupelo.parse
;---------------------------------------------------------------------------------------------------
; https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
; http://blog.fikesfarm.com/posts/2015-12-18-clojurescript-macro-tower-and-loop.html
#?(:cljs (:require-macros
[tupelo.misc]
[tupelo.testy]))
(:require
[clojure.test] ; sometimes this is required - not sure why
[tupelo.parse :as tpar]
[tupelo.misc :as misc]
[tupelo.core :as t :refer [spy spyx spyxx spyx-pretty]]
[tupelo.testy :refer [deftest testing is dotest isnt is= isnt= is-set= is-nonblank=
throws? throws-not? define-fixture]])
#?(:clj (:import [java.lang Math]))
)
Parsing integers:
#?(:cljs
(do
(dotest
(is= 0 (tpar/parse-int "0"))
(is= 15 (tpar/parse-int "15"))
(is= -5 (tpar/parse-int "-5"))
(is= 99999 (tpar/parse-int "99999"))
(throws? (tpar/parse-int ""))
(throws? (tpar/parse-int "05"))
(throws? (tpar/parse-int "123xxx"))
(throws? (tpar/parse-int "12x3"))
(throws? (tpar/parse-int "12.3"))
(throws? (tpar/parse-int "xxx123")))
Parsing floats
(dotest
(is= 0 (tpar/parse-float "0"))
(is= 0 (tpar/parse-float "0.0"))
(is= 12.345 (tpar/parse-float "12.345"))
(is= -5.1 (tpar/parse-float "-5.1"))
(is= 42 (tpar/parse-float "42.0"))
(is= 42 (tpar/parse-float "42"))
(is= 123.45 (tpar/parse-float "1.2345e2"))
(throws? (tpar/parse-float ""))
(throws? (tpar/parse-float "xxx1.23"))
(throws? (tpar/parse-float "1.23xxx"))
(throws? (tpar/parse-float "1.2xx34")))
))

Related

Get floating/decimal portion of a float

I would like:
unknown_function(123.456) -> 456
unknown_function(1234.56) -> 56
Or
unknown_function(123.456) -> "456"
Is there a builtin for this? The builtin trunc/1 does the opposite:
2> trunc(123.456).
123
There is this answer for C: Extract decimal part from a floating point number in C and this for Java: How to get the decimal part of a float?
No there is no BIF for this, but you can do this:
decimal_point(X, DecimalDigits) when X < 0 ->
decimal_point(-X, DecimalDigits);
decimal_point(X, DecimalDigits)->
(X - trunc(X)) * math:pow(10,DecimalDigits).
> decimal_point(2.33, 2).
33
> decimal_point(-2.33, 2).
33
This is inspired by #Dogbert's comment
The algorithm doesnt work using native floats due to floating point representation limits and rounding errors.
However, using https://github.com/tim/erlang-decimal:
frac_to_denom_int(Num, Denom, Precison) ->
{X, _} = string:to_integer(lists:nth(2, string:tokens(decimal:format(decimal:divide(Num, Denom, [{precision, Precison}])), "."))),
X.
E.g.,
frac_to_denom_int("1.0", "3.0", 1000).
> 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
If you don't have a frac,
d_to_denom_int(D_Tup)->
string:to_integer(lists:nth(2, string:tokens(decimal:format(D_Tup), "."))).
d_to_denom_int({0, 123456, -3}).
> 456
Based on #dogbert's comment, passing in one more flag compact on the float_to_list/2 call will help:
lists:nth(2, string:tokens(float_to_list(123.456, [{decimals, 10}, compact]), ".")).
% "456"
If you go over decimals 14, you'll start to see those rounding errors.

"%" and "/" simbols difference in Ruby

I'm trying to solve the FizzBuzz game.
I need to check if a number is divisible by 3. So, when we take a number and divide it by 3, we need that operation to have NO REST, or 0 REST.
The solution given to me is this:
def fizzbuzz(number)
if number % 3 == 0
return "Fizz"
end
Why does they propose to use the "%"symbol? Why not the "/"symbol? Or both work as the same?
How should I check if the division has NO REST?
division operator / - gives the quotient of the division whatever the remainder of the division is. So you cannot determine if a number is perfectly divisible (remainder = 0) or not perfectly divisible (with non-zero remainder) using a division operator (/).
10 / 3
#=> 3
modulo operator % - gives the remainder of the division. If perfectly divisible, the output is 0, if not-perfectly divisible the output is non-zero value.
10 % 3
#=> 1
In your case number % 3 == 0 is true only if number is divisible by 3 with 0 remainder (i.e if number passed into the method frizzbuzz is a multiple of 3 like -12, -3, 3, 6, 9, etc )
Ruby has 4 division operators.
divmod returns the division and the remainder
number = 15
number.divmod(7) # => 2, 1
modulo alias % returns the remainder only
number = 15
number % 7 # => 1
number.modulo(7) # => 1
div alias / returns the integer division if both operands are integers, and floating-point division if either operand is a float.
number = 15
number / 7 # => 2
number.div(7) # => 2
1.0 * number / 7 # => 2.142857142857143
fdiv always returns a full precision floating-point division
number = 15
number.fdiv(7) # => 2.142857142857143
% is the Modulus - Divides left hand operand by right hand operand and returns remainder. \ is just the Divider. No Rest means that x % y == 0.
lets take an example to understand better:
number1 = 12
number2 = 13
lets see if number1 and number2 is devisible by 4 ok?
number1 / 4 = 3 and the rest = 0
number2 / 4 = 3 and the rest = 1
so the "/" operation let us know the result of devision operation
and the "%" operation let us know the rest of devision operation
so if we take our examples the number1 is devisible by 3 because
number1 % 3 = 0 ( the rest )

Lua find operand in a string

I have a Lua string like "382+323" or "32x291" or "94-23", how can I check and return the position of the operands?
I found String.find(s, "[+x-]") did not work. Any ideas?
th> str = '5+3'
th> string.find(str, '[+-x]')
1 1
th> string.find(str, '[+x-]')
2 2
[+-x] is a pattern match for 1 character in the range between "+" and "x".
When you want to use dash as character and not as the meta character you should start or end the character group with it.
print("Type an arithmetic expression, such as 382 x 3 / 15")
expr = io.read()
i = -1
while i do
-- Find the next operator, starting from the position of the previous one.
-- The signals + and - are special characters,
-- so you have to use the % char to escape each one.
-- [The find function returns the indices of s where this occurrence starts and ends][1].
-- Here we are obtaining just the start index.
i = expr:find("[%+x%-/]", i+1)
if i then
print("Operator", expr:sub(i, i), "at position", i)
end
end

how to run the bytecode generated by ruby?

I am new to the Ruby scripting language.
I was learning how to generate the byte code in Ruby.
I found the answer for generating the byte code.
But I don't know how to run that generated byte code. I searched the internet, but I didn't get the answer for this.
Generating a byte code:-
puts RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'").disassemble
The output is,
== disasm: <RubyVM::InstructionSequence:<compiled>#<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] x
0000 trace 1 ( 1)
0002 putobject 50
0004 setlocal x
0006 trace 1
0008 getlocal x
0010 putobject 100
0012 opt_gt <ic:1>
0014 branchunless 20
0016 putstring "foo"
0018 leave
0019 pop
0020 putstring "bar"
0022 leave
I don't know how to execute the same script, by using the generated byte code.
Anyone please explain me how to execute this.
Thanks in advance!
TL;DR; You are looking for .eval method.
The .compile method would return an instance of RubyVM::InstructionSequence class, which has .eval method that evaluates/runs your "compiled" instructions.
iseq = RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'")
iseq.eval # => "bar"
Or, a oneliner:
RubyVM::InstructionSequence.compile("x = 50; x > 100 ? 'foo' : 'bar'").eval

Format string to number with minimum length in lua

For example I need number with minimum 3 digit
"512" --> 512
"24" --> 24.0
"5" --> 5.00
One option is write small function. Using answers here for my case it will be something like this
function f(value, w)
local p = math.ceil(math.log10(value))
local prec = value <= 1 and w - 1 or p > w and 0 or w - p
return string.format('%.' .. prec .. 'f', value)
end
print(f(12, 3))
But may be it is possible just using string.format() or any other simple way?
Ok, it seems this case beyond the string.format power. Thanks to #Schollii, this is my current variant
function f(value, w)
local p = math.ceil(math.log10(value))
local prec = value <= 1 and w - 1 or p > w and 0 or w - p
return string.format('%.' .. prec .. 'f', value)
end
print(f(12, 3))
There is no format code specifically for this since string.format uses printf minus a few codes (like * which would hace simplified the solution I give below). So you have to implement yourself, for example:
function f(num, w)
-- get number of digits before decimal
local intWidth = math.ceil(math.log10(num))
-- if intWidth > w then ... end -- may need this
local fmt='%'..w..'.' .. (w-intWidth) .. 'f'
return string.format(fmt, num)
end
print(f(12, 4))
print(f(12, 3))
print(f(12, 2))
print(f(512, 3))
print(f(24, 3))
print(f(5, 3))
You should probably handle case where integer part doesn't fit in field width given (return ceil or floor?).
You can't. Maximum you can reach - specify floating point precision or digit number, but you can't force output to be like your example. Lua uses C like printf with few limitations reference. Look here for full specifiers list link. Remember unsupported ones.
Writing a function would be the best and only solution, especially as your task looks strange, as it doesn't count decimal dot.

Resources