Can anyone please provide hive udf code for truncating particular column? - hive-udf

I have a column that contain double value 42.2223. I want to truncate the last four digits of this particular column.
Can any one please provide hive UDF for this particular scenario?

If you want to truncate the last four digits and get an integer, you can use the built-in functions floor(double a) or ceiling(double a), depending on the the kind of rounding (upper or lower) that you want.
If you wanted your double to be truncated to d decimal places (and get a double, instead of an integer), you could use round(double a, int d).
EDITED
In order to round without truncating, you can use this
CAST((column * 100) AS int)/100

Wrote an UDF for the above question where we can specify number of characters it can be truncated
package com.hive.udf.truncate;
import java.math.BigDecimal;
import org.apache.hadoop.hive.ql.exec.UDF;
public class Trunc extends UDF {
public double evaluate(double input,int numberOfDecimals){
if ( input > 0) {
return new BigDecimal(String.valueOf(input)).setScale(numberOfDecimals, BigDecimal.ROUND_FLOOR).doubleValue();
}
else {
return new BigDecimal(String.valueOf(input)).setScale(numberOfDecimals, BigDecimal.ROUND_CEILING).doubleValue();
}
}
}

Related

Datetime and iso format

sometimes toString(datetime()) return the milliseconds without the leading zeros to reach the length of 3 (yyyy-MM-dd'T'HH:mm:ss.SSSXXX). Is it a bug or normal behavior?
For example:
2019-11-21T15:59:22.53Z -> it should be 2019-11-21T15:59:22.053Z
2019-11-21T15:59:21.216Z -> OK
2019-11-21T15:30:09.042Z -> OK
This behavior causes an issue when I try to convert the string into a date.
Thank you
Try using the apoc.temporal.format function, specifying the iso_instant type conversion.
For example:
RETURN apoc.temporal.format(datetime("2019-11-21T22:04:19.13Z"), 'iso_instant');
will return:
"2019-11-21T22:04:19.130Z"
[UPDATE]
Since the TOSTRING() function is not documented to return any particular ISO 8601 string format for a datetime, one should not depend on it returning a specific format -- or even returning the same string for the same datetime across versions.
However, if you want a non-APOC approach that works with recent versions of neo4j (like, 3.5.12, on which this was tested), here is an example of one way to modify the current TOSTRING() output string to always have a 3-digit millisecond value:
// Generate a string.
// You can play with the number of digits after ".", and
// even eliminate the "." and any following digits.
WITH TOSTRING(datetime("2019-11-21T22:04:10.1Z")) AS d
// Always return a 3-digit millisecond time in result
WITH d, LENGTH(d) AS lth
RETURN d, CASE WHEN lth < 24
THEN SUBSTRING(d, 0, lth-1) + SUBSTRING('.000Z', lth - 20)
ELSE d END AS result

How to set the minimum count of digits after the decimal point in Dart?

In my shopping app, I want to show the item's price in two formats. In the currency of my country which is the HUF and we don't use decimals.
e.g. HUF 1250 or 1250 Ft
The other is the EUR and there we write two digits after the decimal point. These two digits are always there, even if they are 00.
e.g. EUR 12.00 or 12,00 €
I know how can I set the maximum count of digits with the double.toStringAsFixed() method but I didn't find a solution to the opposite setting. Is there in the Dart API any method to solve my problem or do I need to find an alternative way to do this?
You can define the currency with number format like so:
import 'package:intl/intl.dart';
final oCcy = new NumberFormat("#,##0.00", "en_US");
void main () {
print("Eg. 1: ${oCcy.format(123456789.75)}");
print("Eg. 2: ${oCcy.format(.7)}");
print("Eg. 3: ${oCcy.format(12345678975/100)}");
print("Eg. 4: ${oCcy.format(int.parse('12345678975')/100)}");
print("Eg. 5: ${oCcy.format(double.parse('123456789.75'))}");
}

Int Variable won't let me add data from UI text field

I'm currently working on making a savings app in Xcode 10. I'm working on a feature that lets users add the amount of money they have saved for something into the app through a UI text field. I can't find a way to return the text from the text field to an Integer and add that to the total sum of money that has been saved. Also whenever I tried to add a test variable I got plenty of errors.
var amountSavedSoFar += amountOfMoneySaved
Both I have set to be integers. I'm trying to set amountOfMoneySaved equal to the numbers in the text field, but it doesn't seem to work.
'+=' is not a prefix unary operator
Consecutive statements on a line must be separated by ';'
Type annotation missing in pattern
Unary operator cannot be separated from its operand
You've got a few issues as you mentioned:
amountSavedSoFar is declared in the saveAmount function and will not be persisted if you call that function more than once.
amountSaved.text is not being converted from String to the appropriate type (Int, Double, etc.)
amountSavedSoFar isn't typed or initialized.
Try something like:
var amountSavedSoFar: Int = 0
#IBAction func saveAmount(_ sender: Any) {
//Convert the text and default to zero if conversion fails
amountSavedSoFar += Int(amountSaved.text) ?? 0
}

How do I round a decimal result up in Thymeleaf (same behavior as Math.ceil)?

I am doing table pagination logic for my project using Thymeleaf.
I have two values:
int totalRows
int rowsPerPage
The operation I want to do is something along the lines of Math.ceil((1.0 + totalRows) / rowsPerPage) to store in a variable that represents the total number of pages necessary.
However, I'm not sure how to do that ceil() operation to convert it from a decimal to an integer.
If you are working with Spring then you can add a bean that has the method you want Math.ceil. Then call this method in the template. Something like
#Component
public class ThymeMath {
public int ceil(int a, int b) {
return Math.ceil....
}
}
Then in the template
${#thymeMath.ceil(a, b)}
That is in the case you really need to do it in Thymeleaf. In the more general case you can calculate the variable in the Java code and add it to the model.
You can just call Math.ceil with thymeleaf, use:
${T(Math).ceil(yourNumber)}
Since Math.ceil returns a double type, you can also encapsulate that in the following expression to remove the trailing ".0" if you wish (the last "1" is the min number of integer digits):
${#numbers.formatInteger(T(Math).ceil(yourNumber),1)}

Define Money Fomat in Laravel

I am trying to save money format in laravel 5.1.
Here is table price define:
$table->decimal(price,6,2);
For instance ; when 1.000,50 Turkish Liras saving to MySQL this format 1.00
How can solve this issue?
You can try defining your price like this
$table->decimal('price',9,3);
Where,
9 is the precision, ie 1234567.89 has a precision of 9
3 is the number of decimal places, ie 123456.789 has a scale of 3
In other words, if we use less decimal-places than 3, we can use remaining for real-number places.
You can refer to this link for about precision and scale of database
How do I interpret precision and scale of a number in a database?
I would suggest not using a float value to store currency as decimals, since floats don't act exactly as you would expect them to, due to the way they are stored in the system.
You would be much better off storing the value in "kuruş" (the subunit of Turkish Lira), as it will be much, much easier in the long run.
In other words, storing the lowest unit you think will be ever required, like storing Centi-meters instead of Meters (Centi is originally Greekish name for "0.01" number).
Secondly, if you're using Eloquent you can use mutators/accessors on the Model e.g.
public function getPriceAttribute($price)
{
return $price / 100;
}
public function setPriceAttribute($price)
{
$this->attributes['price'] = $price * 100;
}
That way you don't have to manually convert the price.
Update
If you're using Laravel 9 or above, you can use the new Attribute syntax instead:
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function price(): Attribute
{
return Attribute::make(
get: fn ($price) => $price / 100,
set: fn ($price) => $price * 100,
);
}
Illuminate blueprints do not support money columns. AFAIK, the money column type itself is only supported in a couple of DBMSes.
What you can do is issue an ALTER TABLE statement to the database after the initial CREATE statement:
Schema::create('my_table', function(Blueprint $table) {
$table->decimal('my_money_column', 999, 2);
// ... the rest of the column definitions
});
DB::statement("
ALTER TABLE my_table ALTER COLUMN my_money_column
SET DATA TYPE MONEY;
");
Beware, though, as this will (probably) break cross-DBMS compatibility of your migration scripts.

Resources