Rule to work with float?

Hello,
can somebody give me a hand about converting and working with float?
It’s probably super simple, but … yeah for now I don’t know :wink:

I do have mqtt which reports float 23.42 which is kWh (and no i can’t change source for this situation to report it Wh)
So I need to convert value 23.42 into 23420 to work with it somehow

in rules I know how to work with numbers like
(myitem.state as Number).intValue
but issue is that when I use that, it will convert my 23.42 into 23 only. So is there a way how to multiply my input by 1000 before using it as number.intvalue ?

or can i do math operations directly with float?
Thanks

So you want something like
(myitem.state as Number).doubleValue

Not sure why you can’t just use it as a Number though. Maybe show your Item definition and rule

basically I have changing input
consumption = 23.42 , 23.1, 22.4 etc. defined as Number in items
and then I need to populate min/max (which I know how :wink: ) and calculate range inbetween, which I dont know how without intValue

rule "power consumption min/max/range"
when
    Item Pump_Consumption changed
then
    val max = Pump_Consumption.maximumSince(now.withTimeAtStartOfDay)
    val min = Pump_Consumption.minimumSince(now.withTimeAtStartOfDay)    
    
    if (max !== null && min !== null) {
        val range = (Pump_Consumption_Max.state as Number).intValue - (Pump_Consumption_Min.state as Number).intValue

        postUpdate(Pump_Consumption_Max, max.state)
        postUpdate(Pump_Consumption_Min, min.state)
        postUpdate(Pump_Consumption_Range, range)
    }

if there is a better way, please kick me to the right direction :wink:

Thanks for your help!

No, that’s the way I’d do it, exploiting persistence tools.

well if that’s the right way… is there also a way how to handle this in decimal numbers? as indeed with this code I’m getting range 1 instead of 1.02

I think most efficient way would be to convert decimal into integer and work with it as int, but no idea how and if I can do it in openhab directly

I’m not quite sure what your difficulty is. Wouldn’t you just stop using the integers in the “range” calculation and use doubles instead?

sometimes my brain really sux…
I had an error in one name and overlooked it in log as well.
This works :slight_smile:
I’m dumb and sorry for bothering…

val range = (Pump_Consumption_Max.state as Number).doubleValue - (Pump_Consumption_Min.state as Number).doubleValue

Just a short question here:
As I know OH Itemtype Number is internally BigDecimal?

Until now I use in my rules

(item.state as Number).floatValue

but I think float is not java equivalent for BigDecimal? Better to use doubleValue instead to avoid unnecessary converting internally?

(item.state as Number).doubleValue
1 Like

I doubt it makes much difference really. The types to avoid in rules where possible are the java primitives, which bring some kind of compiling overhead. Not always possible to avoid.

The closest thing to a “native” type for rules is the Number, but of course that can come with units of measurement baggage.

BigDecimal is BigDecimal. It’s not int, short, long, double, or float. When you call *value there is a conversion that takes place. BigDecimal stores numbers in decimal format meaning it can exactly represent most numbers. double represents numbers in IEEE format which has some gaps in the numbers that it can represent.

Use floatValue when you want to convert the BigDecimal to a 32 bit IEEE formatted floating point value. Use doubleValue when you want to convert BigDecimal to a 64 bit IEEE formatted floating point value. But in both cases a conversion is taking place.

Almost always float is sufficient. Just be sure to use whatever is required by the functions you may be calling.