ID:148703
 
I'd swear I saw this in the blue book once, but I can't seem to find it now...

Is there a simple way to format numbers in an output string? (ie. if I have 4.5454545, I only want "4.5" to be displayed). I guess I could do copytext(num2text(N),1,3), but I'm assuming there's a simpler way.
num2text(X-X%0.1) . X-X%N , where N is a number such as 1, 10, 0.1, etc, will shave off all numbers behind the place value of N.
i believe if the 4.454545 part is a var you can do this, not sure though.

round(whatever var here)
In response to Tazor07
That will round it down to 4. If you want the same effect, you need round(X*10)/10, or round(X,0.1), both of which are less compact than my way. =)
Dramstud wrote:
I'd swear I saw this in the blue book once, but I can't seem to find it now...

Is there a simple way to format numbers in an output string? (ie. if I have 4.5454545, I only want "4.5" to be displayed). I guess I could do copytext(num2text(N),1,3), but I'm assuming there's a simpler way.

A more accurate way, yes. A simpler way, no.
proc/Num2Text(n,precision=6)
var/t=""
n=round(n,0.1**precision)
if(n<0)
t="-"
n=-n
if(n>=1000)
var/th=round(n/1000)
t="[t][Num2Text(th,0)],[n/100%10][n/10%10][n%10]"
else
t="[t][n]"
n-=round(n)
if(!n || precision<1) return
t="[t]."
while(precision--)
n*=10
t="[t][n%10]"
return t

Lummox JR
In response to Lummox JR
I'm even having trouble reading that one, Lummox. At least at first glance ;).
In response to Polatrite
Yeah, commenting code like that is usually useful.
In response to Lummox JR
If you're going to be assisting with code problems, you ought to get out of the habit of using 1-letter variables. They just confuse people.
In response to Lummox JR
Lummox JR wrote:
Dramstud wrote:
I'd swear I saw this in the blue book once, but I can't seem to find it now...

Is there a simple way to format numbers in an output string? (ie. if I have 4.5454545, I only want "4.5" to be displayed). I guess I could do copytext(num2text(N),1,3), but I'm assuming there's a simpler way.

A more accurate way, yes. A simpler way, no.
proc/Num2Text(n,precision=6)
> var/t=""
> n=round(n,0.1**precision)
> if(n<0)
> t="-"
> n=-n
> if(n>=1000)
> var/th=round(n/1000)
> t="[t][Num2Text(th,0)],[n/100%10][n/10%10][n%10]"
> else
> t="[t][n]"
> n-=round(n)
> if(!n || precision<1) return
> // t="[t]."
> // while(precision--)
> // n*=10
> // t="[t][n%10]"
> return t

Lummox JR

This works pretty well, though I was getting numbers like "7.6.6" (precision set to 1) until I commented out the last 4 lines before the 'return t'. After that, the output was perfect.

Thanks.
In response to Garthor
Garthor wrote:
That will round it down to 4. If you want the same effect, you need round(X*10)/10, or round(X,0.1), both of which are less compact than my way. =)

It seems like round(X,0.1) is probably the simplest way to go most of the time, unless you want commas for the large numbers (Lummox' solution handles this quite well). While your other suggestion is good for quickly shaving off extra digits, it doesn't round the number properly (ie. X-X%0.1 would round 6.99 to 6.9 instead of 7.0). Hmmm... I just tried the X-X%0.1 method and got a compile error:

error:0.1:attempted division by zero

I tried it again with .1 instead of 0.1:

error:.1: compile failed (possible infinite cross-reference loop)

I guess byond can only 'modulo' whole numbers?

Anyway, thanks for your help guys.
In response to Dramstud
Dramstud wrote:
// if(!n || precision<1) return
// t="[t]."
// while(precision--)
// n*=10
// t="[t][n%10]"
return t</DM>
Lummox JR

This works pretty well, though I was getting numbers like "7.6.6" (precision set to 1) until I commented out the last 4 lines before the 'return t'. After that, the output was perfect.

Thanks.

Correction... last 5 lines (otherwise whole numbers don't get printed at all). I get the feeling maybe I'm not using your Num2Text() proc in the way you intended? Do you have some sample code which illustrates how you use it? Here's what I'm doing:

proc/Print_dice_stats(var/to_who)
if(!dice_roll_history.len)
return
var/list/STAT = list(0,0,0,0,0,0,0,0,0,0,0,0)
for(var/N in dice_roll_history)
STAT[N] ++
to_who << "Dice Roll Statistics for this game:"
for(var/n = 2, n<13, n++)
var/frequency = 100*STAT[n]/dice_roll_history.len
var/pctg = Num2Text(frequency, 1)
to_who << "[n]: [STAT[n]] ([pctg]%)"
Dramstud wrote:
I'd swear I saw this in the blue book once, but I can't seem to find it now...

Is there a simple way to format numbers in an output string? (ie. if I have 4.5454545, I only want "4.5" to be displayed). I guess I could do copytext(num2text(N),1,3), but I'm assuming there's a simpler way.


I usually use something like this:

proc
num_chop(real_num, dec_count)
return round(real_num*10**dec_count)/(10**dec_count)

Just supply your original number, and the number of decimals you want. Is this what you're looking for?
In response to Dramstud
Dramstud wrote:
Correction... last 5 lines (otherwise whole numbers don't get printed at all). I get the feeling maybe I'm not using your Num2Text() proc in the way you intended? Do you have some sample code which illustrates how you use it?

I wrote that on the fly and didn't test it; just gave it a quick run-through in my head. I was hoping I didn't miss anything but that was a risk. Glad you got it to work, though.

Lummox JR
In response to Foomer
Foomer wrote:
If you're going to be assisting with code problems, you ought to get out of the habit of using 1-letter variables. They just confuse people.

Eh; I use them when I feel it's appropriate. Typically I use t for text, n for a number. And i, j, and k may appear as index vars from time to time. It's not such a bad system, as long as not every var is done like that.

Lummox JR
In response to Dramstud
Dramstud wrote:
I guess byond can only 'modulo' whole numbers?

I don't know about using fractional operands, but the first number can have a fractional part to it. When that number has a fractional part, BYOND seems to round() it first, so it chops off the fraction. (Actually round(n) is actually equivalent to floor(n), I'm told.)
This can actually be handy behavior. In Scream of the Stickster I can get a nice compact time display using code something like this (but with obviously shorter var names):
var/timeleft = max(endofround - world.time, 0)
if(timeleft)
stat("Time remaining: [timeleft/600%60]:[timeleft/100%6][timeleft/10%10]")
No need to use round() to chop off the fractional result, since % will do it for me.

It would actually make worlds more sense for BYOND to support fractional mods, though. Until it does, your only way to do it is this:
proc/mod2(x, y)
return x - y * round(x / y)
That should always return a positive result, unlike BYOND's % operator. However I've always despised negative moduli anyway, being a purist.

Lummox JR