如何克服32位来存储数字-2,147,483,647至2,147,483,647

时间:2019-07-04 10:17:30

标签: lua garrys-mod

我尝试为Gmod amd修复一些旧的Basewars脚本,但我尝试修复某些问题,但我不知道我在那里缺少什么。基本上是关于银行脚本的。该银行原本可以存储20亿美元。我想将该存储量扩展到1兆兆。

所以基本上,Basewars Gamemode允许玩家拥有高达10 ^ 18 $的大量资金  = 1百万亿。我看着https://wiki.garrysmod.com/page/Category:number

所以lua基本上使用双精度浮点格式。所以lua使用32位来存储数字,这意味着数字可以在 -2,147,483,647至2,147,483,647。

Basewars游戏模式使用功能来构成10 ^ 18  = 1百万亿

function BaseWars.NumberFormat(num)

    local t = BaseWars.LANG.Numbers
    for i = 1, #t do

        local Div = t[i][1]
        local Str = t[i][2]

        if num >= Div or num <= -Div then

         return string.Comma(math.Round(num / Div, 1)) .. " " .. Str

        end

    end

    return string.Comma(math.Round(num, 1))

end

Gamemode正在使用该派系转换金额。 这是BaseWars.LANG.Numbers:

BaseWars.LANG = {}
BaseWars.LANG.__LANGUAGELOOK = {}

BaseWars.LANG.__LANGUAGELOOK.ENGLISH = {
    Numbers = {
        [5] = {10^6, "Million"},
        [4] = {10^9, "Billion"},
        [3] = {10^12, "Trillion"},
        [2] = {10^15, "Quadtillion"},
        [1] = {10^18, "Quintillion"},
    },

    CURFORMER       = CURRENCY .. "%s",
    CURRENCY        = CURRENCY,
}

所以我知道此功能确实有效,但我不明白,变量num可以那么高! 为什么我知道它起作用了?

这是我尝试过的方法,它可以将容量控制到1兆兆,但到那时我又操纵了另一个问题,但我不知道我做错了什么!

这是原始的:

ENT.Capacity        = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
ENT.Money           = 0
ENT.MaxPaper        = 0

local Clamp = math.Clamp
function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

        end

        self["Set" .. name](self, Val)

    end

end


function ENT:StableNetwork()

    self:GSAT(2, "Capacity")

    self:GSAT(3, "Money", 0, "GetCapacity")
    self:GSAT(4, "Paper", 0, "MaxPaper")
    self:GSAT(5, "Level", 0, "MaxLevel")

end

function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers 


for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do 
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < self.Capacity then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end     

        for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < self.Capacity then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end 

end

if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0
        local cap = tonumber(Cp) or 0

        local moneyPercentage = math.Round( money / cap * 100 ,1)

        draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)

local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
            local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
            local font = fontName .. ".Big"
            if #currentMoney > 16 then

                font = fontName .. ".MedBig"

            end
            if #currentMoney > 20 then

                font = fontName .. ".Med"

            end
            local fh = draw.GetFontHeight(font)

            local StrW,StrH = surface.GetTextSize("")
            local moneyW,moneyH = surface.GetTextSize(currentMoney)
            draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
                w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)


end

这是我所做的更改:

已删除的行: 本地上限= tonumber(Cp)或0

已添加 本地上限= 10 ^ 15 如果self:GetMoney()

ENT.Capacity        = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
local cap = 10^15
ENT.Money           = 0
ENT.MaxPaper        = 0

local Clamp = math.Clamp
function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))

        end

        self["Set" .. name](self, Val)

    end

end


function ENT:StableNetwork()

    self:GSAT(2, "Capacity")

    self:GSAT(3, "Money", 0, "GetCapacity")
    self:GSAT(4, "Paper", 0, "MaxPaper")
    self:GSAT(5, "Level", 0, "MaxLevel")

end

function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers 


for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do 
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < cap then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end     

        for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
            if v:CPPIGetOwner() == self:CPPIGetOwner() then
                if self:GetMoney() < cap then
                    local allmoney = v:GetMoney()
                    v:TakeMoney(allmoney)
                    self:AddMoney(allmoney)
                end
            end
        end 

end

if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0


        local moneyPercentage = math.Round( money / cap * 100 ,1)

        draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)

local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
            local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
            local font = fontName .. ".Big"
            if #currentMoney > 16 then

                font = fontName .. ".MedBig"

            end
            if #currentMoney > 20 then

                font = fontName .. ".Med"

            end
            local fh = draw.GetFontHeight(font)

            local StrW,StrH = surface.GetTextSize("")
            local moneyW,moneyH = surface.GetTextSize(currentMoney)
            draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
                w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)


end

所以现在,如果您进入游戏,它看起来像这样: 现在我遇到的问题是,当它收集到钱时,它最多可以存钱20亿美元,如果我尝试更改

local money = tonumber(self:GetMoney()) or 0

local money =self:GetMoney()

我直得-2.1比尔

或者我尝试更改最小最大值:

function ENT:GSAT(slot, name,  min, max)

    self:NetworkVar("Int", slot, name)

    local getVar = function(minMax)

        if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
        if self[minMax] and isnumber(self[minMax]) then return self[minMax] end

        return minMax or 0

    end

    self["Add" .. name] = function(_, var)

            local Val = self["Get" .. name](self) + var

            if min and max then

                Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

            end

            self["Set" .. name](self, Val)

    end

    self["Take" .. name] = function(_, var)

        local Val = self["Get" .. name](self) - var

        if min and max then

            Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

        end

        self["Set" .. name](self, Val)

    end

end

基本上这些行:

Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)

如果我运行游戏,银行将只收取最多2比尔的钱,然后将其变为-2.1Bil。在那一点上,我不知道为什么以及何时将值设置为bug时会自动将其设置为-2.1 Bil。 math.Round会创建此bug还是funktion返回仅返回完整整数?

thx寻求帮助

1 个答案:

答案 0 :(得分:0)

由于银行使用的网络变量是整数,因此只能存储$(2 ^ 31-1)到$-(2 ^ 31-1)。尝试将其更改为网络浮动:

-- ...
function ENT:GSAT(slot, name,  min, max)

    -- self:NetworkVar("Int", slot, name), changes into:
    self:NetworkVar("Float", slot, name)
-- ...

但是,请注意,随着玩家积累的金钱越多,这些数字的准确性就越低。