How to set decimal points in CEL - cumulocity

I've been doing some calculation using CEL. Because of the complication of the calculation, the result ends up with some long decimal points. I'm just wondering is there any function that I can transform the data like 23.012372983659365034701 to 23.01?
Thank you.

In CEL the numbers are Java BigDecimal (unless you create it as some other data type).
The getNumber() method for example returns BigDecimal.
You can use the setScale function of BigDecimal (see https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#setScale(int,%20java.math.RoundingMode))

Related

How to get TrimEnd() to stop at a specific character

I have a series of percentage values saved in a database that look something like this:
Percentage
_____________
100.00000
50.00000
74.02500
When I display the values to the screen, I'd like to trim unnecessary zeroes from the end of the string along with the decimal point so the above examples become:
Percentage
_____________
100
50
74.025
I'm currently using the following code:
displayVal = rawVal.TrimEnd({"0"c, "."c})
but this code continues to trim after the decimal if there are additional zeroes. I also tried:
displayVal = rawVal.TrimEnd(New String({"0", "."}))
which almost works. It just leaves the decimal point.
Is there a way to do what I want using TrimEnd() or do I need to switch to regex?
As Tim already mentioned in the comments, if the data type in the DB is already some numerical type, it would be best to keep it in that type and then use the appropriate numeric formatting when converting it to a string for output. If, however, the input data is already a string, then that's not an option. In that cast, the simplest option is to just do two trims in series, like this:
Private Function RemoveUnecessaryZeros(input As String) As String
Return input.TrimEnd("0"c).TrimEnd("."c)
End Function
However, that doesn't give you a lot of flexibility, it doesn't remove preceding zeros, and it does nothing to reformat the string using the current culture. If that matters, you could instead parse the value into a numeric type and then use the desired string formatting options to re-output it to a string. For instance:
Private Function RemoveUnecessaryZeros(input As String) As String
Dim result As Double
If Double.TryParse(input, result) Then
Return result.ToString()
Else
Return input
End If
End Function
However, when you do it that way, you may potentially lose precision along the way, depending on the input numbers and the data type you choose to parse it with. If you need more control over the parsing/reformatting and you want to keep it purely in strings so no precision is lost, then you may want to consider using regex. For instance:
Private Function RemoveUnecessaryZeros(input As String) As String
Dim m As Match = Regex.Match(input, "[1-9]\d*(\.([1-9]|0+[1-9])+)?")
If m.Success Then
Return m.Value
Else
Return input
End If
End Function

Decimal place VB.NET simple

I know that is the simple question but how can i return sum of my variable d with decimal places ?
it's always return me 8, not 8.0. But if my variable will be for examle 4.1 it will return 8.2 how it works with 0 in VB.NET?
Public Shared Sub Main()
Dim d As Decimal = 4.0
Console.WriteLine(d+d)
End Sub
use Decimal.ToString() method while writing to console.
Try something like this, pass the decimal in as a string, or else modify this function, but this should do the trick
Private Function ConvertStringToDec(str As String) As Decimal
Dim temp As String = String.Format(".{0}", str)
Dim d As Decimal
Decimal.TryParse(temp, d)
Return dec
End Function
To expand on David's answer, you can manipulate the output of any string you want by changing the first argument of String.Format. For example, if you want two decimal places you can use:
String.Format("{0:0.00}", d+d)
for three decimal places:
String.Format("{0:0.000}", d+d)
The number before the colon corresponds to the argument number. The numbers after the colon specify the format you want. For example with two arguments using different formats:
String.Format("{0:0.0}, {1:0.00}", d, n)
If you had d=4 and n=2 and you printed this out using the above formatter, you would end up with 4.0 (corresponding to the 0 argument with 0.0 format) and a 2.00 (corresponding to the 1 argument with 0.00 format)
and so on. There are a ton of options, not only for numbers, but for dates and more. Check out this easy-to-read website to understand its use a bit more clearly.
Hope this helps!

VBA "Left"-function as integer

been playing around with the "left"-function in VBA and noticed that the result is stored as a string. For example:
Left(ws2.range("C2").value,3)
Where ws2 is some worksheet and c2 is some cell in ws2 containing, say, 1234.
The left function would then return "123" but it would be formated as a string. This in turn causes errors for me when i try to access a directories key with this string (which is not possible). I've found a workaround where I :
dim tag as integer
tag = Left(ws2.range("C2").value,3)
This would cause the tag with the value 123 to be stored as an integer which I then can use for accessing the directory.
But i'm wondering if it's possible to modify the "left"-function to return values as integers? or any other format for that matter (long, variant, range, whatever)
Notice that I have figured out a solution but I thought it might be helpful to others and/or a interesting discussion.
For this it is easiest to use Cint() function. There is no need to modify functions, you can always create yours.
The proper way to do it would be to use the Cint() function to cast an expression to an integer.
For details see https://msdn.microsoft.com/en-us/library/fctcwhw9(v=vs.84).aspx
Here are some more conversion functions:
CInt() 'convert to integer
CLng() 'convert to long (long is preferred over integer since integer only has 2 bytes in VBA)
CDbl() 'convert to double
CDec() 'convert to decimal (variable has to be declared as variant)
Made it an answer :)
cint(left(ws2.range("C2").value,3)) would be "better" as you're still relying on VBA to make the conversion for you, also checking the output first to work out if you in fact need to use a long maybe. Also checking the input string is numeric first of all would also be a good check.
using cint
function IntLeft(byval value as string, byval length as integer) as Integer
IntLeft=0 'default if non numeric
if isnumeric(value) then
IntLeft=cint(left(value,length))
end if
end function
using int
function IntLeft(byval value as string, byval length as integer) as Integer
IntLeft=int(left(value,length)) 'int returns the first numbers as an int, 0 if no numbers
end function
You can use Abs function instead to return the left function as integer.
i.e., Abs(Left(ws2.range("C2").value,3))

VBA: passing variables (from worksheet) into functions

A quick one for noob like me!
So usually I pass in some range of data from worksheet into function like that:
public function foo (someRange as range)
dim someData as double
if IsNumeric(someRange.value), do some crap
end function
The problem occur when I try to code some function that uses this function foo. Instead of range i would like to pass in a double(). So if I were to fix this, i can either:
a. I have seen some other site uses "someRange as Variant" instead (which then avoid problem like i face). However, is it "good coding practice"?
b. use a wrapper function foo_wrap instead
You could use a Variant and then TypeName to find out what kind of argument was supplied:
?TypeName(range("A1"))
Range
?TypeName(45.66)
Double
?TypeName(array(34.5,56.7))
Variant()
Personally, I would just create two separate Functions. Using one function would just be messy to me. For a single function NOT to just duplicate code, it would have to extract all the Range values into a Double array. This just tells us that it should be two functions.
Creating a wrapper-function is an option, but I'll leave you to decide whether this is a good solution for you.
If you did want to pursue a multi-purpose function then you could investigate ParamArray:
Used only as the last argument in arglist to indicate that the final
argument is an Optional array of Variant elements.
This would allow you to create a Function that behaves similarly to the built-in functions (SUM, etc.) which can accept a variable number of arguments, which can be Ranges and/or values. However, particularly as you are a noob, I would ignore this possibility for a while. The KISS principle.

IsNumeric returns true for strings containing a D character

I had a strange error in a VB6 app this morning and it all stems from the fact that IsNumeric is not working as I expected. Can someone shed some light on why? To me this seems like a bug.
This code displays 4.15877E+62 in a message box:
Dim strMessage As String
strMessage = "0415877D57"
If IsNumeric(strMessage) Then
MsgBox CDbl(strMessage)
Else
MsgBox "not numeric"
End If
I am guessing that the runtime engine is incorrectly thinking that the D is in fact an E?
I think this is a bug though as the exact same code in VB.NET outputs not numeric
Is this a known issue with IsNumeric?
If you check the VB6 docs:
Note Floating-point values can be expressed as mmmEeee or mmmDeee, in which mmm is the mantissa and eee is the exponent (a power of 10). The highest positive value of a Single data type is 3.402823E+38, or 3.4 times 10 to the 38th power; the highest positive value of a Double data type is 1.79769313486232D+308, or about 1.8 times 10 to the 308th power. Using D to separate the mantissa and exponent in a numeric literal causes the value to be treated as a Double data type. Likewise, using E in the same fashion treats the value as a Single data type.
I've been using my own IsNumber function for a long time exactly because of this situation. IsNumeric can also return true for certain money symbols, like this: IsNumeric("$34.20").
My IsNumber function looks like this:
Public Function IsNumber(ByVal Data As String) As Boolean
If Data = "" Then
IsNumber = False
Exit Function
End If
IsNumber = IsNumeric(Data & "e0")
End Function
The idea here is... if there is already an e or d in the data, adding another will cause the data to NOT be numeric using the IsNumeric check. You can easily change this function to only allow for integers by replacing "e0" with ".0e0". Want just positive integers? then use this: IsNumeric("-" & Data & ".0e0")
The only downside of this method is that an empty string normally is not numeric, but when you append "e0" to it, it becomes numeric so you need to add a check for that, like I did in my code.
I suggest making a custom validator. Do you want to allow 0-9 only? What about negatives? Commas? I never cared for Microsoft's implementation, but I understand it.