This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Whitecatblack's profile picture

Eliminating Decimal Places and Points By Converting to String

Started by Whitecatblack, 30 May 2014 - 10:04 PM
Whitecatblack #1
Posted 31 May 2014 - 12:04 AM
So this is my first post on this forum, so we will see how it goes.

Hi all,

-Project Background (Thaumcraft)-
So recently I have been playing around with Thaumcraft's (and Thaumic Tinkerer's) interactions with ComputerCraft, and am now attempting to make an Infusion Altar with automatic refilling of an array(51) of surrounding aspect jars through the use of mana beans. Instead of using logistics pipes and requesting mana beans through them, I have decided, for the sake of difficulty, to use TT's Aspectualizer. The Aspectualizer will read what aspects are on an inputted item and how many of that aspect there are. A brief, simple overview of the process: I have a gold chest (Iron Chests) filled with mana beans in its first 51 slots. Each slot contains a full stack of one type of mana bean, and the chest itself only has 1 stack of each type of bean (hence 51 stacks), while the other slots are blocked/filled with cobblestone. A turtle next to the chest will scan each stack of the chest in an Aspectualizer and create a table that displays which aspect is in which slot. The main computer will then know which stack to pull from, when needed, by using said table. The chest refills itself through the use of an ME export bus attached to an ME system, which, hypothetically, would be gathering mana beans from a farm.This project involves designing a program to not only read the jars and to know when to refill them, but also to display the amount of aspects I have of each kind in the surrounding jars on a monitor nearby. This will include having the amount of each aspect color-coded by how full the jar is. And yes, I am aware that a man by the name of Direwolf20 has done something similar (I use the DW20 pack).

-Current Issue/Question-
At the moment, progress is going great, and I seem to be able to get done what I want with a bit of fiddling with the code. The issue I ran into today involves the displaying of the aspects on a monitor portion. Let me first explain how exactly I am going about reading the jars, in the situation that someone may be unfamiliar with it. I am connecting the jars to my computer through wired modems and networking cable, although the modems themselves won't attach directly onto the jars themselves, as they are not full blocks. Instead, I attach a Peripheral Proxy(OpenPeripheralAddons) to the jar and then a modem to the proxy. Through this process, I am now able to connect the jars as peripherals and read them using peripheral.getAspects(). This function, from TT, returns: {[1.0]={name=aspect, quantity=amount}}, a table with one entry. We can extract that inner table using peripheral.getAspects()[1.0], which returns: {name=Aspect, quantity=amount}. From here we can directly extract the name (peripheral.getAspects()[1.0]["name"]) and quantity (peripheral.getAspects()[1.0]["quantity"] fairly easily. So, using that info, I can write the data onto my monitor and do, well, whatever I want with it from there. However, I ran into a problem, which I couldn't find an easy answer to, although I may just be blind. The problem I referred to earlier was that the output for the quantity of aspect in each jar displayed a whole number with a tenth's place (i.e. 30.0). Since I didn't want this on my monitor, I attempted to somehow remove the decimal part of the number, and was eventually able to, kinda.

tl;dr When I extract the 'quantity' from the aspect jars, it displays with a tenth's place (i.e. 30.0), which I want to remove for displaying (i.e. 30).

The way I got rid of the tenth's place was an accidental discovery through my random testing of different methods. I used string.format(quantity), which, surprisingly, gave me what I wanted. I am led to believe, however, that somehow that function turned the number into a string while also eliminating the decimal.

So (finally), my question to you all is first: How does string.format() work in general, and then in specific how I managed to use it. Second: Instead of using this to delete the decimal, what would you all use? I would rather do it a different way as if I want to compare the quantity to other numbers, I am unable to do so directly.

(In case you were curious, here is the test program in which I stumbled upon this)
http://pastebin.com/PxUnyf4A

[Edit] Added to background info, as some might find it useful.

Thanks for the help,
Whitecatblack
Edited on 02 June 2014 - 07:20 PM
Bomb Bloke #2
Posted 31 May 2014 - 07:54 AM
string.format() won't alter the value inside the variable you pass it, but rather returns a new value that is a string. If you only call it when you go to render to your display, and never overwrite the original variable with its output, then it shouldn't prevent you from performing comparisons later.

Eg, there's nothing stopping you from doing this sort of thing:

print("I have "..string.format(peripheral.getAspects()[1]["quantity"]).." thingies.")

Note that you don't need to specify index "1.0" - a simple "1" will suffice. Off the top of my head, I reckon math.floor() or tostring() would have similar results in this particular case.

You can read more about string.format() here, and in fact the whole page is worth reading.

If you're ever unsure what type a given variable is, the type() function can generally tell you.
Whitecatblack #3
Posted 31 May 2014 - 05:35 PM
Hi Bomb Bloke,
Thanks for the response, I am glad my long message didn't scare everyone away ^_^/> . Incoming long message #2.

string.format() won't alter the value inside the variable you pass it, but rather returns a new value that is a string. If you only call it when you go to render to your display, and never overwrite the original variable with its output, then it shouldn't prevent you from performing comparisons later.
Yea, this is in fact how I had gone about doing it:

uquantity = peripheral.call(j, "getAspects")[1]["quantity"] --unformatted amount
And then later when I wanted to print it:

fquantity = string.format(uquantity) --formatted amount

Note that you don't need to specify index "1.0" - a simple "1" will suffice.
Ah, was not aware of that, thanks.

Off the top of my head, I reckon math.floor() or tostring() would have similar results in this particular case.
When I was playing around with this earlier(before I posted), I had tried math.floor() and math.ceil() and expected them to work as well, but both of them still return with a tenth's place when I write it to the monitor (30.0). As far as I am aware, tostring() does the same thing as string.format() with no arguments, as they both convert the input directly into a string, right?

So with these thoughts in mind, I just ran some testing with my code. You may have already been aware of this, but I hadn't: I found that monitor.write(quantity) will always output with at least decimal point and tenth's place, disregarding the actual format of the input number if it is less accurate than that (i.e. 30 will write to 30.0, and 30.00 will write to 30.0, but 30.01 will write to 30.01). So this got me thinking: What if I term.redirect to the monitor and then print the results? And I can tell you, through my testing, I have found that print() will always take the input value to a whole number if it can (i.e. 30 will print 30, 30.00 will print 30, but 30.01 will print 30.01). So that was interesting, at least to me.

tl;dr So through my testing, it appears I have two options to choose from when wanting to write a number with no decimal places or decimals points to a monitor: Either I can convert the input number directly to a string and then write that string to the monitor, and use the original, not string, value when I want to compare the input number. Or I can term.redirect() all my operations to the monitor and directly print the input on the monitor, and then compare the input number directly when needed.

So my new question now, with this newfound information: Is there a way to monitor.write(), or something similar, a value, not a string, to a monitor without including the decimal point/places without having to redirect to the monitor? If so, I can't find it.

Anything I missed? Appreciate the help mate,
Whitecatblack
Lyqyd #4
Posted 31 May 2014 - 08:47 PM
print() does a tostring() on all of its arguments anyway, so you're still converting it to a string before writing it to the monitor, even if you don't have to explicitly do so. If you want to drop all decimal places, even if they are non-zero, this should do it:


monitor.write(tostring(math.floor(value)))

That also won't modify the number stored in value.
Whitecatblack #5
Posted 31 May 2014 - 11:09 PM
Hai Lyqyd ^_^/>

Lyqyd said:
print() does a tostring() on all of its arguments anyway
Had forgotten about that (smack), thanks for reminding me.

So that all pretty much wraps up my 'problem'; as an obligatory follow-up question, in case someone stumbles upon this thread in the hope to solve their own problems: How would you go about displaying a number output with decimal places, as a string (i.e. function outputs 30.00, convert output to string "30.00")? Because if some function were to output a number like 30.0, and you wanted to print() that to the console, how could one do that? Since we know print() automatically sets the input number equal to a string, which will remove the decimal since they are zeros, how would(could) this be possible?

Appreciate the assistance from both of you,
Whitecatblack
Lyqyd #6
Posted 01 June 2014 - 01:27 AM
The correct way to do it is with string.format. You'd do:


print(string.format("%#.2f", value))

If I recall correctly, however, the string.format in LuaJ is slightly broken, so you'd have to do other weird tricks to get it to work.
Whitecatblack #7
Posted 01 June 2014 - 01:35 AM
Alright, thanks for the info. I think that about wraps this up, peace.

[Edit] If anyone has questions about the topic or about my project, feel free to post a response.

Whitecatblack
Edited on 01 June 2014 - 12:30 AM