Golang ParseFloat not accurate in example - parsing

I've been working on a project where I have to convert a string to a uint, to make sure some money values are matching:
total, err := strconv.ParseFloat(paymentResp.Transactions[0].Amount.Total, 64)
if err != nil {
return ctx.JSON(http.StatusBadRequest, err.Error())
}
if o.TotalPrice != uint(total*100) {
return ctx.JSON(http.StatusBadRequest, "Unable to verify amount paid")
}
But I've seemingly found a problem when trying to do the strconv.ParseFloat() on a couple of numbers, then attempting to multiply them by 100 (to get the cents value).
I've created an example here: Go Playground
f, _ := strconv.ParseFloat("79.35", 64)
fmt.Println(uint(f*100)) //7934
f2, _ := strconv.ParseFloat("149.20", 64)
fmt.Println(uint(f2*100)) //14919
Is ParseFloat() what I should be using in this scenario? If not, I'd love to hear a brief explanation on this, as I'm still a programmer in learning.

Go uses IEEE-754 binary floating-point numbers. Floating-point numbers are imprecise. Don't use them for financial transactions. Use integers.
For example,
package main
import (
"fmt"
"strconv"
"strings"
)
func parseCents(s string) (int64, error) {
n := strings.SplitN(s, ".", 3)
if len(n) != 2 || len(n[1]) != 2 {
err := fmt.Errorf("format error: %s", s)
return 0, err
}
d, err := strconv.ParseInt(n[0], 10, 56)
if err != nil {
return 0, err
}
c, err := strconv.ParseUint(n[1], 10, 8)
if err != nil {
return 0, err
}
if d < 0 {
c = -c
}
return d*100 + int64(c), nil
}
func main() {
s := "79.35"
fmt.Println(parseCents(s))
s = "149.20"
fmt.Println(parseCents(s))
s = "-149.20"
fmt.Println(parseCents(s))
s = "149.2"
fmt.Println(parseCents(s))
}
Playground: https://play.golang.org/p/mGuO51QWyIv
Output:
7935 <nil>
14920 <nil>
-14920 <nil>
0 format error: 149.2

Based on #peterSO's answer, with some bugfix and enhancement:
https://play.golang.org/p/YcRLeEJ7lTA
package main
import (
"fmt"
"strconv"
"strings"
)
func parseCents(s string) (int64, error) {
var ds string
var cs string
n := strings.SplitN(s, ".", 3)
switch len(n) {
case 1:
ds = n[0]
cs = "0"
case 2:
ds = n[0]
switch len(n[1]) {
case 1:
cs = n[1] + "0"
case 2:
cs = n[1]
default:
return 0, fmt.Errorf("invalid format:%s", s)
}
default:
return 0, fmt.Errorf("invalid format:%s", s)
}
d, err := strconv.ParseInt(ds, 10, 0)
if err != nil {
return 0, err
}
c, err := strconv.ParseUint(cs, 10, 0)
if err != nil {
return 0, err
}
cents := d * 100
if strings.HasPrefix(s, "-") {
cents -= int64(c)
} else {
cents += int64(c)
}
return cents, nil
}
func main() {
examples := map[string]int64{
"79.35": 7935,
"149.20": 14920,
"-149.20": -14920,
"149.2": 14920,
"-0.12": -12,
"12": 1200,
"1.234": 0,
"1.2.34": 0,
}
for s, v := range examples {
cents, err := parseCents(s)
fmt.Println(cents, cents == v, err)
}
}

you can split the string, and parse them to an int.
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
a:=strings.Split("75.35",".")
if len(a)>2{
panic("badly formatted price")
}
v,_:=strconv.ParseInt(a[1],10,64)
w,_:=strconv.ParseInt(a[0],10,64)
fmt.Println(uint(w*100+v))
}
its working in this link https://play.golang.org/p/5s_FTAKSo9M

Related

Rego Object matching and comparison

I'm trying to match the domain key ("domain":"example.com") from the given input, and return an error if the values are not identical. This is what I've thought of so far, but I can't seem to match the domain key, thus the tests are failing. Any advice would be appreciated.
OPA Policy:
package main
import data.config
default warning_mode = []
warning_mode = config.warn_mode { config.warn_mode }
array_contains(arr, elem) {
arr[_] = elem
}
exception[rules] {
rules := config.exceptions.rules
}
deny_missing_config[msg] {
not config
msg := "Missing configuration file"
}
## Main
aws_ses_dkim[a] {
a := input.resource_changes[_]
a.type == "aws_ses_domain_dkim"
}
aws_ses_domain[e] {
e := input.resource_changes[_]
e.type == "aws_ses_domain_identity"
}
ses_missing_dkim[msg] {
a := aws_ses_dkim[_]
e := aws_ses_domain[_]
walk(a, [["values", "domain"], x])
walk(e, [["values", "domain"], y])
err := x - y
not err == set()
msg := sprintf("Placeholder error", [err, a.address, e.address])
}
## Test Cases
deny_ses_missing_dkim[msg]{
not array_contains(warning_mode, "ses_missing_dkim")
ses_missing_dkim[_] != []
msg := ses_missing_dkim[_]
}
warn_ses_missing_dkim[msg]{
array_contains(warning_mode, "ses_missing_dkim")
ses_missing_dkim[_] != []
msg := ses_missing_dkim[_]
}
test_ses_missing_dkim_invalid {
i := data.mock.invalid_ses_dkim
r1 := warn_ses_missing_dkim with input as i with data.config.warn_mode as []
count(r1) == 0
r2 := warn_ses_missing_dkim with input as i with data.config.warn_mode as ["ses_missing_dkim"]
count(r2) == 1
r3 := deny_ses_missing_dkim with input as i with data.config.warn_mode as []
count(r3) == 1
r4 := deny_ses_missing_dkim with input as i with data.config.warn_mode as ["ses_missing_dkim"]
count(r4) == 0
count(r1) + count(r2) == 1
count(r3) + count(r4) == 1
}
test_ses_missing_dkim_valid {
i := data.mock.ses_dkim
r1 := warn_ses_missing_dkim with input as i with data.config.warn_mode as []
r2 := warn_ses_missing_dkim with input as i with data.config.warn_mode as ["ses_missing_dkim"]
r3 := deny_ses_missing_dkim with input as i with data.config.warn_mode as []
r4 := deny_ses_missing_dkim with input as i with data.config.warn_mode as ["ses_missing_dkim"]
count(r1) + count(r2) + count(r3) + count(r4) == 0
}
Input (Terraform JSON):
"resource_changes":[
{
"address":"aws_ses_domain_dkim.example",
"mode":"managed",
"type":"aws_ses_domain_dkim",
"name":"example",
"provider_name":"registry.terraform.io/hashicorp/aws",
"schema_version":0,
"values":{
"domain":"example.com"
},
"sensitive_values":{
"dkim_tokens":[
]
}
},
{
"address":"aws_ses_domain_identity.example",
"mode":"managed",
"type":"aws_ses_domain_identity",
"name":"example",
"provider_name":"registry.terraform.io/hashicorp/aws",
"schema_version":0,
"values":{
"domain":"example.com"
},
"sensitive_values":{
}
}
]
The x and y values retrieved by the walk function will be strings, so err := x - s isn't going to work. If you want a set of values, you could wrap the walk call in a set comprehension to get a set of all values:
ses_missing_dkim[msg] {
a := aws_ses_dkim[_]
e := aws_ses_domain[_]
xs := {x | walk(a, [["values", "domain"], x])}
ys := {y | walk(e, [["values", "domain"], y])}
err := xs - ys
not err == set()
msg := sprintf("Placeholder error", [err, a.address, e.address])
}
You probably don't need walk here though, as the values are always at a known path.

how to show full results for X in double (for e.g X=3.45)?

I had made this code to resolve an equation which X is unknown (Ax + B = 0) it's working fine; but cannot show full results for X in double (for e.g X=3.45) value how can I do it thank you for your help
import 'dart:io' show stdin;
import 'dart:core' show FormatException, num, print;
import 'dart:math' show Random;
void main() {
for(var i=0 ; i<1 ; i--) {
try {
print("Equation N° 1 : ax+b=0");
print("Enter value of A");
var a = stdin.readLineSync();
var A = num.parse(a!);
print("Enter value of B");
var b = stdin.readLineSync();
var B = num.parse(b!);
var X;
if (B != 0) {
if (A != 0) {
print("A = $A");
print("B = $B");
X = -B ~/ A;
print("X=$X");
} else if (A == 0) {
print(A);
print(B);
print("The equation, does not admit a solution.");
print("X = No solution ");
}
} else {
if (A != 0) {
print(A);
print(B);
print("the equation, admit 0 for solution");
print("X = 0");
} else {
print(A);
print(B);
print("the equation, admits an infinity of solutions");
print("X = +∞");
}
}
}
on FormatException {
print("Invalid Value");
print("Please Entre a Valid Value");
}
}
}
remove the ~ symbol in X = -B ~/ A.
and it will work fine
You are using the integer division : X = -B ~/ A
Try without the ~ symbol.
A & B should be double type and X as well

Find longest common substring of array of Strings

In my Swift 3.0 app, I want to determine the best name for something by finding the longest common substring of 6 to 12 strings.
Example strings:
ON/OFF office lights
DIM office lights
VALUE office lights
FB office lights
FB VALUE office lights
Desired output:
office lights
I've come across multiple StackOverflow answers for the longest subsequence but haven't been able to adapt any of them to my needs..
Any help would be greatly appreciated!
I converted Java & C++ code into Swift 3 , collected from GeeksForGeeks Longest Common Subsequence & Longest Common Substring.
It works !
class LongestCommon
{
// Returns length of LCS for X[0..m-1], Y[0..n-1]
private static func lcSubsequence(_ X : String , _ Y : String ) -> String
{
let m = X.characters.count
let n = Y.characters.count
var L = Array(repeating: Array(repeating: 0, count: n + 1 ) , count: m + 1)
// Following steps build L[m+1][n+1] in bottom up fashion. Note
// that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1]
for i in stride(from: 0, through: m, by: 1)
{
for j in stride(from: 0, through: n, by: 1)
{
if i == 0 || j == 0
{
L[i][j] = 0;
}
else if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
L[i][j] = L[i-1][j-1] + 1
}
else
{
L[i][j] = max(L[i-1][j], L[i][j-1])
}
}
}
// Following code is used to print LCS
var index = L[m][n]
// Create a character array to store the lcs string
var lcs = ""
// Start from the right-most-bottom-most corner and
// one by one store characters in lcs[]
var i = m
var j = n
while (i > 0 && j > 0)
{
// If current character in X[] and Y are same, then
// current character is part of LCS
if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
lcs.append(X[X.index( X.startIndex , offsetBy: (i - 1) )])
i-=1
j-=1
index-=1
}
// If not same, then find the larger of two and
// go in the direction of larger value
else if (L[i-1][j] > L[i][j-1])
{
i-=1
}
else
{
j-=1
}
}
// return the lcs
return String(lcs.characters.reversed())
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
private static func lcSubstring(_ X : String , _ Y : String ) -> String
{
let m = X.characters.count
let n = Y.characters.count
var L = Array(repeating: Array(repeating: 0, count: n + 1 ) , count: m + 1)
var result : (length : Int, iEnd : Int, jEnd : Int) = (0,0,0)
// Following steps build L[m+1][n+1] in bottom up fashion. Note
// that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1]
for i in stride(from: 0, through: m, by: 1)
{
for j in stride(from: 0, through: n, by: 1)
{
if i == 0 || j == 0
{
L[i][j] = 0;
}
else if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
L[i][j] = L[i-1][j-1] + 1
if result.0 < L[i][j]
{
result.length = L[i][j]
result.iEnd = i
result.jEnd = j
}
}
else
{
L[i][j] = 0 //max(L[i-1][j], L[i][j-1])
}
}
}
// Following code is used to print LCS
let lcs = X.substring(with: X.index(X.startIndex, offsetBy: result.iEnd-result.length)..<X.index(X.startIndex, offsetBy: result.iEnd))
// return the lcs
return lcs
}
// driver program
class func subsequenceOf(_ strings : [String] ) -> String
{
var answer = strings[0] // For on string answer is itself
for i in stride(from: 1, to: strings.count, by: 1)
{
answer = lcSubsequence(answer,strings[i])
}
return answer
}
class func substringOf(_ strings : [String] ) -> String
{
var answer = strings[0] // For on string answer is itself
for i in stride(from: 1, to: strings.count, by: 1)
{
answer = lcSubstring(answer,strings[i])
}
return answer
}
}
Usage :
let strings = ["ON/OFF office lights",
"DIM office lights",
"VALUE office lights",
"FB office lights",
"FB VALUE office lights"]
print(LongestCommon.subsequenceOf(strings))
print(LongestCommon.substringOf(strings))

Dafny syntax error in function

I am struggling with dafny syntax.
searchAndReplace receives three arrays of chars. Let's imagine line is [s][n][a][k][e]; pat is [n][a] and dst is [h][i]. I want to search for all the occurrences of pat in line and replace it with dst resulting in [s][h][i][k][e]
Method findwill return the indice of the first letter in line that is equal to pat.
Method deletewill remove pat from line at the variable at returned at find, and move all the others elements after at+p to the left in order to fill the null spaces.
Method insertwill make space in order to dst be added to lineat atby moving all the characters between atand at + p ppositions to the right.
I created an auxiliar function which will compare patand dst in order to verify that they aren't equal(if they were it would be replacing infinitely time dstin line in case patexisted in line)
For now i'm receiving the error "then expected" on the following section of code inside function checkIfEqual:
if(pat.Length != dst.Length) {
return false;
}
The full code:
method searchAndReplace(line:array<char>, l:int,
pat:array<char>, p:int,
dst:array<char>, n:int)returns(nl:int)
requires line != null && pat!=null && dst!=null;
requires !checkIfEqual(pat, dst);
requires 0<=l<line.Length;
requires 0<=p<pat.Length;
requires 0<=n<dst.Length;
modifies line;
{
var at:int := 0;
var p:int := n;
while(at != -1 )
invariant -1<=at<=l;
{
at := find(line, l, dst, n);
delete(line, l, at, p);
insert(line, l, pat, p, at);
}
var length:int := line.Length;
return length;
}
function checkIfEqual(pat:array<char>, dst:array<char>):bool
requires pat!=null && dst!=null;
reads pat;
reads dst;
{
var i:int := 0;
if(pat.Length != dst.Length) {
return false;
}
while(i<dst.Length) {
if(pat[i] != dst[i]){
return false;
}
i := i + 1;
}
return true;
}
method insert(line:array<char>, l:int, nl:array<char>, p:int, at:int)
requires line != null && nl != null;
requires 0 <= l+p <= line.Length && 0 <= p <= nl.Length ;
requires 0 <= at <= l;
modifies line;
ensures forall i :: (0<=i<p) ==> line[at+i] == nl[i]; // error
{
var i:int := 0;
var positionAt:int := at;
while(i<l && positionAt < l)
invariant 0<=i<l+1;
invariant at<=positionAt<=l;
{
line[positionAt+p] := line[positionAt];
line[positionAt] := ' ';
positionAt := positionAt + 1;
i := i + 1;
}
positionAt := at;
i := 0;
while(i<p && positionAt < l)
invariant 0<=i<=p;
invariant at<=positionAt<=l;
{
line[positionAt] := nl[i];
positionAt := positionAt + 1;
i := i + 1;
}
}
method find(line:array<char>, l:int, pat:array<char>, p:int) returns (pos:int)
requires line!=null && pat!=null
requires 0 <= l < line.Length
requires 0 <= p < pat.Length
ensures 0 <= pos < l || pos == -1
{
var iline:int := 0;
var ipat:int := 0;
pos := -1;
while(iline<l && ipat<pat.Length)
invariant 0<=iline<=l
invariant 0<=ipat<=pat.Length
invariant -1 <= pos < iline
{
if(line[iline]==pat[ipat] && (line[iline]!=' ' && pat[ipat]!=' ')){
if(pos==-1){
pos := iline;
}
ipat:= ipat + 1;
} else {
if(ipat>0){
if(line[iline] == pat[ipat-1]){
pos := pos + 1;
}
}
ipat:=0;
pos := -1;
}
if(ipat==p) {
return;
}
iline := iline + 1;
}
return;
}
method delete(line:array<char>, l:nat, at:nat, p:nat)
requires line!=null
requires l <= line.Length
requires at+p <= l
modifies line
ensures line[..at] == old(line[..at])
ensures line[at..l-p] == old(line[at+p..l])
{
var i:nat := 0;
while(i < l-(at+p))
invariant i <= l-(at+p)
invariant at+p+i >= at+i
invariant line[..at] == old(line[..at])
invariant line[at..at+i] == old(line[at+p..at+p+i])
invariant line[at+i..l] == old(line[at+i..l]) // future is untouched
{
line[at+i] := line[at+p+i];
i := i+1;
}
}
functions in Dafny are pure, inductively defined and use a different syntax to the imperative methods. You cannot use imperative language features inside a function. In this case you are not allowed to use:
The conditional statement if cond { s1* } else { s2* }
The loop statement while cond { s1* }
Instead the body of the function must be an expression:
predicate checkIfEqual(pat:array<char>, dst:array<char>)
requires pat!=null && dst!=null;
reads pat;
reads dst;
{
pat.Length == dst.Length
&& forall i:nat :: i < pat.Length ==> pat[i] == dst[i]
}
Although it is not needed here, Dafny does have a conditional expression (ite):
predicate checkIfEqual(pat:array<char>, dst:array<char>)
requires pat!=null && dst!=null;
reads pat;
reads dst;
{
if pat.Length != dst.Length then false
else forall i:nat :: i < pat.Length ==> pat[i] == dst[i]
}
Note that:
You cannot put a loop in the body of a function, but you may use recursion
predicate is a shorthand for a function that returns bool

Elixir parse binary data?

​for example:
I have a binary look like this:
bin1 = "2\nok\n3\nbcd\n\n"​
or
bin2 = "2\nok\n3\nbcd\n1\na\n\n"​
and so on...
The format is
byte_size \n bytes \n byte_size \n bytes \n \n
I want parse binary get
["ok", "bcd"]
how to implement in Elixir or Erlang ?
Go version
a Go version parse this
func (c *Client) parse() []string {
resp := []string{}
buf := c.recv_buf.Bytes()
var idx, offset int
idx = 0
offset = 0
for {
idx = bytes.IndexByte(buf[offset:], '\n')
if idx == -1 {
break
}
p := buf[offset : offset+idx]
offset += idx + 1
//fmt.Printf("> [%s]\n", p);
if len(p) == 0 || (len(p) == 1 && p[0] == '\r') {
if len(resp) == 0 {
continue
} else {
c.recv_buf.Next(offset)
return resp
}
}
size, err := strconv.Atoi(string(p))
if err != nil || size < 0 {
return nil
}
if offset+size >= c.recv_buf.Len() {
break
}
v := buf[offset : offset+size]
resp = append(resp, string(v))
offset += size + 1
}
return []string{}
}
Thanks
A more flexible solution:
result = bin
|> String.split("\n")
|> Stream.chunk(2)
|> Stream.map(&parse_bytes/1)
|> Enum.filter(fn s -> s != "" end)
def parse_bytes(["", ""]), do: ""
def parse_bytes([byte_size, bytes]) do
byte_size_int = byte_size |> String.to_integer
<<parsed :: binary-size(byte_size_int)>> = bytes
parsed
end
I wrote a solution:
defp parse("\n") do
[]
end
defp parse(data) do
{offset, _} = :binary.match(data, "\n")
size = String.to_integer(binary_part(data, 0, offset))
value = binary_part(data, offset + 1, size)
len = offset + 1 + size + 1
[value] ++ parse(binary_part(data, len, byte_size(data) - len))
end
The Elixir mailing list provides another one:
defp parse_binary("\n"), do: []
defp parse_binary(binary) do
{size, "\n" <> rest} = Integer.parse(binary)
<<chunk :: [binary, size(size)], "\n", rest :: binary>> = rest
[chunk|parse_binary(rest)]
end

Resources